vite-node
Advanced tools
Comparing version 0.1.18 to 0.1.19
@@ -5,2 +5,3 @@ declare type FetchFunction = (id: string) => Promise<{ | ||
}>; | ||
declare type ResolveIdFunction = (id: string, importer?: string) => Promise<ViteNodeResolveId | null>; | ||
interface ModuleCache { | ||
@@ -13,2 +14,3 @@ promise?: Promise<any>; | ||
fetchModule: FetchFunction; | ||
resolveId: ResolveIdFunction; | ||
root: string; | ||
@@ -20,2 +22,9 @@ base?: string; | ||
} | ||
interface ViteNodeResolveId { | ||
external?: boolean | 'absolute' | 'relative'; | ||
id: string; | ||
meta?: Record<string, any> | null; | ||
moduleSideEffects?: boolean | 'no-treeshake' | null; | ||
syntheticNamedExports?: boolean | string | null; | ||
} | ||
@@ -22,0 +31,0 @@ declare class ViteNodeRunner { |
321
dist/cli.js
import minimist from 'minimist'; | ||
import { red, dim } from 'kolorist'; | ||
import { createServer } from 'vite'; | ||
import { ViteNodeServer } from './server.js'; | ||
import { ViteNodeRunner } from './client.js'; | ||
import 'fs'; | ||
import 'mlly'; | ||
import './utils.js'; | ||
import 'url'; | ||
import 'pathe'; | ||
import 'module'; | ||
import 'vm'; | ||
import { existsSync } from 'fs'; | ||
import { isNodeBuiltin, isValidNodeImport } from 'mlly'; | ||
import { fileURLToPath, pathToFileURL } from 'url'; | ||
import { dirname, resolve } from 'pathe'; | ||
import { builtinModules, createRequire } from 'module'; | ||
import vm from 'vm'; | ||
const isWindows = process.platform === "win32"; | ||
function slash(str) { | ||
return str.replace(/\\/g, "/"); | ||
} | ||
function normalizeId(id, base) { | ||
if (base && id.startsWith(base)) | ||
id = `/${id.slice(base.length)}`; | ||
return id.replace(/^\/@id\/__x00__/, "\0").replace(/^\/@id\//, "").replace(/^__vite-browser-external:/, "").replace(/^node:/, "").replace(/[?&]v=\w+/, "?").replace(/\?$/, ""); | ||
} | ||
function isPrimitive(v) { | ||
return v !== Object(v); | ||
} | ||
function toFilePath(id, root) { | ||
let absolute = slash(id).startsWith("/@fs/") ? id.slice(4) : id.startsWith(dirname(root)) ? id : id.startsWith("/") ? slash(resolve(root, id.slice(1))) : id; | ||
if (absolute.startsWith("//")) | ||
absolute = absolute.slice(1); | ||
return isWindows && absolute.startsWith("/") ? fileURLToPath(pathToFileURL(absolute.slice(1)).href) : absolute; | ||
} | ||
const ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/; | ||
const ESM_FOLDER_RE = /\/esm\/(.*\.js)$/; | ||
const defaultInline = [ | ||
/\/vitest\/dist\//, | ||
/vitest-virtual-\w+\/dist/, | ||
/virtual:/, | ||
/\.ts$/, | ||
ESM_EXT_RE, | ||
ESM_FOLDER_RE | ||
]; | ||
const depsExternal = [ | ||
/\.cjs.js$/, | ||
/\.mjs$/ | ||
]; | ||
function guessCJSversion(id) { | ||
if (id.match(ESM_EXT_RE)) { | ||
for (const i of [ | ||
id.replace(ESM_EXT_RE, ".mjs"), | ||
id.replace(ESM_EXT_RE, ".umd.js"), | ||
id.replace(ESM_EXT_RE, ".cjs.js"), | ||
id.replace(ESM_EXT_RE, ".js") | ||
]) { | ||
if (existsSync(i)) | ||
return i; | ||
} | ||
} | ||
if (id.match(ESM_FOLDER_RE)) { | ||
for (const i of [ | ||
id.replace(ESM_FOLDER_RE, "/umd/$1"), | ||
id.replace(ESM_FOLDER_RE, "/cjs/$1"), | ||
id.replace(ESM_FOLDER_RE, "/$1") | ||
]) { | ||
if (existsSync(i)) | ||
return i; | ||
} | ||
} | ||
} | ||
async function shouldExternalize(id, options, cache = new Map()) { | ||
if (!cache.has(id)) | ||
cache.set(id, _shouldExternalize(id, options)); | ||
return cache.get(id); | ||
} | ||
async function _shouldExternalize(id, options) { | ||
if (isNodeBuiltin(id)) | ||
return id; | ||
id = patchWindowsImportPath(id); | ||
if (matchExternalizePattern(id, options == null ? void 0 : options.inline)) | ||
return false; | ||
if (matchExternalizePattern(id, options == null ? void 0 : options.external)) | ||
return id; | ||
const isNodeModule = id.includes("/node_modules/"); | ||
id = isNodeModule ? guessCJSversion(id) || id : id; | ||
if (matchExternalizePattern(id, defaultInline)) | ||
return false; | ||
if (matchExternalizePattern(id, depsExternal)) | ||
return id; | ||
if (isNodeModule && await isValidNodeImport(id)) | ||
return id; | ||
return false; | ||
} | ||
function matchExternalizePattern(id, patterns) { | ||
if (!patterns) | ||
return false; | ||
for (const ex of patterns) { | ||
if (typeof ex === "string") { | ||
if (id.includes(`/node_modules/${ex}/`)) | ||
return true; | ||
} else { | ||
if (ex.test(id)) | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
function patchWindowsImportPath(path) { | ||
if (path.match(/^\w:\\/)) | ||
return `file:///${slash(path)}`; | ||
else if (path.match(/^\w:\//)) | ||
return `file:///${path}`; | ||
else | ||
return path; | ||
} | ||
let SOURCEMAPPING_URL = "sourceMa"; | ||
SOURCEMAPPING_URL += "ppingURL"; | ||
class ViteNodeServer { | ||
constructor(server, options = {}) { | ||
this.server = server; | ||
this.options = options; | ||
this.promiseMap = new Map(); | ||
} | ||
shouldExternalize(id) { | ||
return shouldExternalize(id, this.options.deps); | ||
} | ||
async fetchModule(id) { | ||
const externalize = await this.shouldExternalize(toFilePath(id, this.server.config.root)); | ||
if (externalize) | ||
return { externalize }; | ||
const r = await this.transformRequest(id); | ||
return { code: r == null ? void 0 : r.code }; | ||
} | ||
async resolveId(id, importer) { | ||
return this.server.pluginContainer.resolveId(id, importer, { ssr: true }); | ||
} | ||
async transformRequest(id) { | ||
if (!this.promiseMap.has(id)) { | ||
this.promiseMap.set(id, this._transformRequest(id).finally(() => { | ||
this.promiseMap.delete(id); | ||
})); | ||
} | ||
return this.promiseMap.get(id); | ||
} | ||
getTransformMode(id) { | ||
var _a, _b, _c, _d; | ||
const withoutQuery = id.split("?")[0]; | ||
if ((_b = (_a = this.options.transformMode) == null ? void 0 : _a.web) == null ? void 0 : _b.some((r) => withoutQuery.match(r))) | ||
return "web"; | ||
if ((_d = (_c = this.options.transformMode) == null ? void 0 : _c.ssr) == null ? void 0 : _d.some((r) => withoutQuery.match(r))) | ||
return "ssr"; | ||
if (withoutQuery.match(/\.([cm]?[jt]sx?|json)$/)) | ||
return "ssr"; | ||
return "web"; | ||
} | ||
async _transformRequest(id) { | ||
let result = null; | ||
const mode = this.getTransformMode(id); | ||
if (mode === "web") { | ||
result = await this.server.transformRequest(id); | ||
if (result) | ||
result = await this.server.ssrTransform(result.code, result.map, id); | ||
} else { | ||
result = await this.server.transformRequest(id, { ssr: true }); | ||
} | ||
if (this.options.sourcemap !== false && result && !id.includes("node_modules")) | ||
withInlineSourcemap(result); | ||
return result; | ||
} | ||
} | ||
async function withInlineSourcemap(result) { | ||
const { code, map } = result; | ||
if (code.includes(`${SOURCEMAPPING_URL}=`)) | ||
return result; | ||
if (map) | ||
result.code = `${code} | ||
//# ${SOURCEMAPPING_URL}=data:application/json;charset=utf-8;base64,${Buffer.from(JSON.stringify(map), "utf-8").toString("base64")} | ||
`; | ||
return result; | ||
} | ||
class ViteNodeRunner { | ||
constructor(options) { | ||
this.options = options; | ||
this.root = options.root || process.cwd(); | ||
this.moduleCache = options.moduleCache || new Map(); | ||
this.externalCache = new Map(); | ||
builtinModules.forEach((m) => this.externalCache.set(m, m)); | ||
} | ||
async executeFile(file) { | ||
return await this.cachedRequest(`/@fs/${slash(resolve(file))}`, []); | ||
} | ||
async executeId(id) { | ||
return await this.cachedRequest(id, []); | ||
} | ||
async cachedRequest(rawId, callstack) { | ||
var _a, _b; | ||
const id = normalizeId(rawId, this.options.base); | ||
const fsPath = toFilePath(id, this.root); | ||
if ((_a = this.moduleCache.get(fsPath)) == null ? void 0 : _a.promise) | ||
return (_b = this.moduleCache.get(fsPath)) == null ? void 0 : _b.promise; | ||
const promise = this.directRequest(id, fsPath, callstack); | ||
this.setCache(fsPath, { promise }); | ||
return await promise; | ||
} | ||
async directRequest(id, fsPath, callstack) { | ||
callstack = [...callstack, id]; | ||
const request = async (dep) => { | ||
var _a; | ||
if (callstack.includes(dep)) { | ||
const cacheKey = toFilePath(dep, this.root); | ||
if (!((_a = this.moduleCache.get(cacheKey)) == null ? void 0 : _a.exports)) | ||
throw new Error(`Circular dependency detected | ||
Stack: | ||
${[...callstack, dep].reverse().map((p) => `- ${p}`).join("\n")}`); | ||
return this.moduleCache.get(cacheKey).exports; | ||
} | ||
return this.cachedRequest(dep, callstack); | ||
}; | ||
if (this.options.requestStubs && id in this.options.requestStubs) | ||
return this.options.requestStubs[id]; | ||
const { code: transformed, externalize } = await this.options.fetchModule(id); | ||
if (externalize) { | ||
const mod = await interpretedImport(externalize, this.options.interpretDefault ?? true); | ||
this.setCache(fsPath, { exports: mod }); | ||
return mod; | ||
} | ||
if (transformed == null) | ||
throw new Error(`failed to load ${id}`); | ||
const url = pathToFileURL(fsPath).href; | ||
const exports = {}; | ||
this.setCache(fsPath, { code: transformed, exports }); | ||
const __filename = fileURLToPath(url); | ||
const moduleProxy = { | ||
set exports(value) { | ||
exportAll(exports, value); | ||
exports.default = value; | ||
}, | ||
get exports() { | ||
return exports.default; | ||
} | ||
}; | ||
const context = this.prepareContext({ | ||
__vite_ssr_import__: request, | ||
__vite_ssr_dynamic_import__: request, | ||
__vite_ssr_exports__: exports, | ||
__vite_ssr_exportAll__: (obj) => exportAll(exports, obj), | ||
__vite_ssr_import_meta__: { url }, | ||
require: createRequire(url), | ||
exports, | ||
module: moduleProxy, | ||
__filename, | ||
__dirname: dirname(__filename) | ||
}); | ||
const fn = vm.runInThisContext(`async (${Object.keys(context).join(",")})=>{{${transformed} | ||
}}`, { | ||
filename: fsPath, | ||
lineOffset: 0 | ||
}); | ||
await fn(...Object.values(context)); | ||
return exports; | ||
} | ||
prepareContext(context) { | ||
return context; | ||
} | ||
setCache(id, mod) { | ||
if (!this.moduleCache.has(id)) | ||
this.moduleCache.set(id, mod); | ||
else | ||
Object.assign(this.moduleCache.get(id), mod); | ||
} | ||
} | ||
function hasNestedDefault(target) { | ||
return "__esModule" in target && target.__esModule && "default" in target.default; | ||
} | ||
function proxyMethod(name, tryDefault) { | ||
return function(target, key, ...args) { | ||
const result = Reflect[name](target, key, ...args); | ||
if (isPrimitive(target.default)) | ||
return result; | ||
if (tryDefault && key === "default" || typeof result === "undefined") | ||
return Reflect[name](target.default, key, ...args); | ||
return result; | ||
}; | ||
} | ||
async function interpretedImport(path, interpretDefault) { | ||
const mod = await import(path); | ||
if (interpretDefault && "default" in mod) { | ||
const tryDefault = hasNestedDefault(mod); | ||
return new Proxy(mod, { | ||
get: proxyMethod("get", tryDefault), | ||
set: proxyMethod("set", tryDefault), | ||
has: proxyMethod("has", tryDefault), | ||
deleteProperty: proxyMethod("deleteProperty", tryDefault) | ||
}); | ||
} | ||
return mod; | ||
} | ||
function exportAll(exports, sourceModule) { | ||
for (const key in sourceModule) { | ||
if (key !== "default") { | ||
try { | ||
Object.defineProperty(exports, key, { | ||
enumerable: true, | ||
configurable: true, | ||
get() { | ||
return sourceModule[key]; | ||
} | ||
}); | ||
} catch (_err) { | ||
} | ||
} | ||
} | ||
} | ||
const argv = minimist(process.argv.slice(2), { | ||
@@ -73,2 +373,5 @@ "alias": { | ||
return node.fetchModule(id); | ||
}, | ||
resolveId(id, importer) { | ||
return node.resolveId(id, importer); | ||
} | ||
@@ -75,0 +378,0 @@ }); |
import { builtinModules, createRequire } from 'module'; | ||
import { pathToFileURL, fileURLToPath } from 'url'; | ||
import { fileURLToPath, pathToFileURL } from 'url'; | ||
import vm from 'vm'; | ||
import { resolve, dirname } from 'pathe'; | ||
import { slash, normalizeId, toFilePath, isPrimitive } from './utils.js'; | ||
import { dirname, resolve } from 'pathe'; | ||
const isWindows = process.platform === "win32"; | ||
function slash(str) { | ||
return str.replace(/\\/g, "/"); | ||
} | ||
function normalizeId(id, base) { | ||
if (base && id.startsWith(base)) | ||
id = `/${id.slice(base.length)}`; | ||
return id.replace(/^\/@id\/__x00__/, "\0").replace(/^\/@id\//, "").replace(/^__vite-browser-external:/, "").replace(/^node:/, "").replace(/[?&]v=\w+/, "?").replace(/\?$/, ""); | ||
} | ||
function isPrimitive(v) { | ||
return v !== Object(v); | ||
} | ||
function toFilePath(id, root) { | ||
let absolute = slash(id).startsWith("/@fs/") ? id.slice(4) : id.startsWith(dirname(root)) ? id : id.startsWith("/") ? slash(resolve(root, id.slice(1))) : id; | ||
if (absolute.startsWith("//")) | ||
absolute = absolute.slice(1); | ||
return isWindows && absolute.startsWith("/") ? fileURLToPath(pathToFileURL(absolute.slice(1)).href) : absolute; | ||
} | ||
class ViteNodeRunner { | ||
@@ -8,0 +26,0 @@ constructor(options) { |
import { existsSync } from 'fs'; | ||
import { isNodeBuiltin, isValidNodeImport } from 'mlly'; | ||
import { slash, toFilePath } from './utils.js'; | ||
import 'url'; | ||
import 'pathe'; | ||
import { fileURLToPath, pathToFileURL } from 'url'; | ||
import { dirname, resolve } from 'pathe'; | ||
const isWindows = process.platform === "win32"; | ||
function slash(str) { | ||
return str.replace(/\\/g, "/"); | ||
} | ||
function toFilePath(id, root) { | ||
let absolute = slash(id).startsWith("/@fs/") ? id.slice(4) : id.startsWith(dirname(root)) ? id : id.startsWith("/") ? slash(resolve(root, id.slice(1))) : id; | ||
if (absolute.startsWith("//")) | ||
absolute = absolute.slice(1); | ||
return isWindows && absolute.startsWith("/") ? fileURLToPath(pathToFileURL(absolute.slice(1)).href) : absolute; | ||
} | ||
const ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/; | ||
@@ -44,14 +54,14 @@ const ESM_FOLDER_RE = /\/esm\/(.*\.js)$/; | ||
} | ||
async function shouldExternalize(id, config, cache = new Map()) { | ||
async function shouldExternalize(id, options, cache = new Map()) { | ||
if (!cache.has(id)) | ||
cache.set(id, _shouldExternalize(id, config)); | ||
cache.set(id, _shouldExternalize(id, options)); | ||
return cache.get(id); | ||
} | ||
async function _shouldExternalize(id, config) { | ||
async function _shouldExternalize(id, options) { | ||
if (isNodeBuiltin(id)) | ||
return id; | ||
id = patchWindowsImportPath(id); | ||
if (matchExternalizePattern(id, config == null ? void 0 : config.inline)) | ||
if (matchExternalizePattern(id, options == null ? void 0 : options.inline)) | ||
return false; | ||
if (matchExternalizePattern(id, config == null ? void 0 : config.external)) | ||
if (matchExternalizePattern(id, options == null ? void 0 : options.external)) | ||
return id; | ||
@@ -109,2 +119,5 @@ const isNodeModule = id.includes("/node_modules/"); | ||
} | ||
async resolveId(id, importer) { | ||
return this.server.pluginContainer.resolveId(id, importer, { ssr: true }); | ||
} | ||
async transformRequest(id) { | ||
@@ -139,3 +152,3 @@ if (!this.promiseMap.has(id)) { | ||
} | ||
if (result && !id.includes("node_modules")) | ||
if (this.options.sourcemap !== false && result && !id.includes("node_modules")) | ||
withInlineSourcemap(result); | ||
@@ -142,0 +155,0 @@ return result; |
@@ -1,4 +0,8 @@ | ||
interface ExternalizeOptions { | ||
interface DepsHandlingOptions { | ||
external?: (string | RegExp)[]; | ||
inline?: (string | RegExp)[]; | ||
/** | ||
* Try to guess the CJS version of a package when it's invalid ESM | ||
* @default true | ||
*/ | ||
fallbackCJS?: boolean; | ||
@@ -10,2 +14,3 @@ } | ||
}>; | ||
declare type ResolveIdFunction = (id: string, importer?: string) => Promise<ViteNodeResolveId | null>; | ||
interface ModuleCache { | ||
@@ -18,2 +23,3 @@ promise?: Promise<any>; | ||
fetchModule: FetchFunction; | ||
resolveId: ResolveIdFunction; | ||
root: string; | ||
@@ -25,4 +31,22 @@ base?: string; | ||
} | ||
interface ViteNodeResolveId { | ||
external?: boolean | 'absolute' | 'relative'; | ||
id: string; | ||
meta?: Record<string, any> | null; | ||
moduleSideEffects?: boolean | 'no-treeshake' | null; | ||
syntheticNamedExports?: boolean | string | null; | ||
} | ||
interface ViteNodeServerOptions { | ||
deps?: ExternalizeOptions; | ||
/** | ||
* Inject inline sourcemap to modules | ||
* @default true | ||
*/ | ||
sourcemap?: boolean; | ||
/** | ||
* Deps handling | ||
*/ | ||
deps?: DepsHandlingOptions; | ||
/** | ||
* Tranform method for modules | ||
*/ | ||
transformMode?: { | ||
@@ -34,2 +58,2 @@ ssr?: RegExp[]; | ||
export { ExternalizeOptions, FetchFunction, ModuleCache, ViteNodeRunnerOptions, ViteNodeServerOptions }; | ||
export { DepsHandlingOptions, FetchFunction, ModuleCache, ResolveIdFunction, ViteNodeResolveId, ViteNodeRunnerOptions, ViteNodeServerOptions }; |
{ | ||
"name": "vite-node", | ||
"version": "0.1.18", | ||
"version": "0.1.19", | ||
"description": "Vite as Node.js runtime", | ||
@@ -21,2 +21,3 @@ "homepage": "https://github.com/vitest-dev/vitest#readme", | ||
"import": "./dist/index.js", | ||
"require": "./dist/index.cjs", | ||
"types": "./index.d.ts" | ||
@@ -26,2 +27,3 @@ }, | ||
"import": "./dist/client.js", | ||
"require": "./dist/client.cjs", | ||
"types": "./client.d.ts" | ||
@@ -31,2 +33,3 @@ }, | ||
"import": "./dist/server.js", | ||
"require": "./dist/server.cjs", | ||
"types": "./server.d.ts" | ||
@@ -36,2 +39,3 @@ }, | ||
"import": "./dist/utils.js", | ||
"require": "./dist/utils.cjs", | ||
"types": "./utils.d.ts" | ||
@@ -38,0 +42,0 @@ } |
import { ViteDevServer, TransformResult } from 'vite'; | ||
interface ExternalizeOptions { | ||
interface DepsHandlingOptions { | ||
external?: (string | RegExp)[]; | ||
inline?: (string | RegExp)[]; | ||
/** | ||
* Try to guess the CJS version of a package when it's invalid ESM | ||
* @default true | ||
*/ | ||
fallbackCJS?: boolean; | ||
} | ||
interface ViteNodeResolveId { | ||
external?: boolean | 'absolute' | 'relative'; | ||
id: string; | ||
meta?: Record<string, any> | null; | ||
moduleSideEffects?: boolean | 'no-treeshake' | null; | ||
syntheticNamedExports?: boolean | string | null; | ||
} | ||
interface ViteNodeServerOptions { | ||
deps?: ExternalizeOptions; | ||
/** | ||
* Inject inline sourcemap to modules | ||
* @default true | ||
*/ | ||
sourcemap?: boolean; | ||
/** | ||
* Deps handling | ||
*/ | ||
deps?: DepsHandlingOptions; | ||
/** | ||
* Tranform method for modules | ||
*/ | ||
transformMode?: { | ||
@@ -17,3 +39,3 @@ ssr?: RegExp[]; | ||
declare function guessCJSversion(id: string): string | undefined; | ||
declare function shouldExternalize(id: string, config?: ExternalizeOptions, cache?: Map<string, Promise<string | false>>): Promise<string | false>; | ||
declare function shouldExternalize(id: string, options?: DepsHandlingOptions, cache?: Map<string, Promise<string | false>>): Promise<string | false>; | ||
@@ -33,2 +55,3 @@ declare class ViteNodeServer { | ||
}>; | ||
resolveId(id: string, importer?: string): Promise<ViteNodeResolveId | null>; | ||
transformRequest(id: string): Promise<TransformResult | null | undefined>; | ||
@@ -35,0 +58,0 @@ private getTransformMode; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
61615
19
1646
14
1