vite-node 0.0.5 → 0.0.140

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,7 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Anthony Fu <https://github.com/antfu>
3
+ Copyright (c) 2021-Present Anthony Fu <https://github.com/antfu>
4
+ Copyright (c) 2021-Present Matias Capeletto <https://github.com/patak-dev>
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -2,12 +2,20 @@
2
2
 
3
3
  [![NPM version](https://img.shields.io/npm/v/vite-node?color=a1b858&label=)](https://www.npmjs.com/package/vite-node)
4
4
 
5
- Vite as Node runtime.
5
+ Vite as Node runtime. The engine powers [Vitest](https://github.com/vitest-dev/vitest).
6
6
 
7
- > **EXPERIMENTAL**
7
+ ## Features
8
+
9
+ - Out-of-box ESM & TypeScript support (possible for more with plugins)
10
+ - Top-level await
11
+ - Vite plugins, resolve, aliasing
12
+ - Respect `vite.config.ts`
13
+ - Shims for `__dirname` and `__filename` in ESM
14
+ - Access to native node modules like `fs`, `path`, etc.
8
15
 
16
+ ## CLI Usage
9
17
 
10
- ## Usage
18
+ Run JS/TS file on Node.js using Vite's resolvers and transformers.
11
19
 
12
20
  ```bash
13
21
  npx vite-node index.ts
@@ -19,29 +27,41 @@ Options:
19
27
  npx vite-node -h
20
28
  ```
21
29
 
22
- ## Features
30
+ ## Programmatic Usage
23
31
 
24
- - Out-of-box ESM & TypeScript support (possible for more with plugins)
25
- - Top-level await
26
- - Vite plugins, resolve, aliasing
27
- - Respect `vite.config.ts`
28
- - Shims for `__dirname` and `__filename` in ESM
29
- - Access to native node modules like `fs`, `path`, etc.
30
- - Watch mode (like `nodemon`)
32
+ In Vite Node, the server and runner (client) are separated, so you can integrate them in different contexts (workers, cross-process, or remote) if needed. The demo below shows a simple example of having the server and running in the same context
31
33
 
32
- ## When NOT to Use
34
+ ```ts
35
+ import { createServer } from 'vite'
36
+ import { ViteNodeServer } from 'vite-node/server'
37
+ import { ViteNodeRunner } from 'vite-node/client'
33
38
 
34
- - Production, yet - in very early stage, check it later
35
- - Most of the time, when other tools can do that job
36
- - We need to start a Vite server upon each execution, which inevitably introduces some overhead. Only use it when you want the same behavior as Vite or the powerful plugins system (for example, testing components with a Vite-specific setup).
39
+ // create vite server
40
+ const server = await createServer()
41
+ // this is need to initialize the plugins
42
+ await server.pluginContainer.buildStart({})
37
43
 
38
- ## Why?
44
+ // create vite-node server
45
+ const node = new ViteNodeServer(server)
39
46
 
40
- It runs Vite's id resolving, module transforming, and most importantly, the powerful plugins system!
47
+ // create vite-node runner
48
+ const runner = new ViteNodeRunner({
49
+ root: server.config.root,
50
+ base: server.config.base,
51
+ // when having the server and runner in a different context,
52
+ // you will need to handle the communication between them
53
+ // and pass to this function
54
+ fetchModule(id) {
55
+ return node.fetchModule(id)
56
+ },
57
+ })
41
58
 
42
- ## How?
59
+ // execute the file
60
+ await runner.run('./example.ts')
43
61
 
44
- It fires up a Vite dev server, transforms the requests, and runs them in Node.
62
+ // close the vite server
63
+ await server.close()
64
+ ```
45
65
 
46
66
  ## Credits
47
67
 
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ interface CliOptions {
2
+ files?: string[];
3
+ _?: string[];
4
+ root?: string;
5
+ config?: string;
6
+ }
7
+
8
+ export { CliOptions };
package/dist/cli.js ADDED
@@ -0,0 +1,78 @@
1
+ import minimist from 'minimist';
2
+ import { red, dim } from 'kolorist';
3
+ import { createServer } from 'vite';
4
+ import { ViteNodeServer } from './server.js';
5
+ import { ViteNodeRunner } from './client.js';
6
+ import 'fs';
7
+ import 'mlly';
8
+ import './utils.js';
9
+ import 'url';
10
+ import 'pathe';
11
+ import 'module';
12
+ import 'vm';
13
+
14
+ const argv = minimist(process.argv.slice(2), {
15
+ "alias": {
16
+ r: "root",
17
+ c: "config",
18
+ h: "help",
19
+ w: "watch",
20
+ s: "silent"
21
+ },
22
+ "--": true,
23
+ "string": ["root", "config"],
24
+ "boolean": ["help", "watch", "silent"],
25
+ unknown(name) {
26
+ if (name[0] === "-") {
27
+ console.error(red(`Unknown argument: ${name}`));
28
+ help();
29
+ process.exit(1);
30
+ }
31
+ return true;
32
+ }
33
+ });
34
+ if (argv.help) {
35
+ help();
36
+ process.exit(0);
37
+ }
38
+ if (!argv._.length) {
39
+ console.error(red("No files specified."));
40
+ help();
41
+ process.exit(1);
42
+ }
43
+ process.argv = [...process.argv.slice(0, 2), ...argv["--"] || []];
44
+ run(argv);
45
+ function help() {
46
+ console.log(`
47
+ Usage:
48
+ $ vite-node [options] [files]
49
+
50
+ Options:
51
+ -r, --root <path> ${dim("[string]")} use specified root directory
52
+ -c, --config <file> ${dim("[string]")} use specified config file
53
+ -w, --watch ${dim("[boolean]")} restart on file changes, similar to "nodemon"
54
+ -s, --silent ${dim("[boolean]")} do not emit errors and logs
55
+ --vue ${dim("[boolean]")} support for importing Vue component
56
+ `);
57
+ }
58
+ async function run(options = {}) {
59
+ const files = options.files || options._ || [];
60
+ const server = await createServer({
61
+ logLevel: "error",
62
+ clearScreen: false,
63
+ configFile: options.config,
64
+ root: options.root
65
+ });
66
+ await server.pluginContainer.buildStart({});
67
+ const node = new ViteNodeServer(server);
68
+ const runner = new ViteNodeRunner({
69
+ root: server.config.root,
70
+ base: server.config.base,
71
+ fetchModule(id) {
72
+ return node.fetchModule(id);
73
+ }
74
+ });
75
+ for (const file of files)
76
+ await runner.run(file);
77
+ await server.close();
78
+ }
@@ -0,0 +1,32 @@
1
+ declare type FetchFunction = (id: string) => Promise<{
2
+ code?: string;
3
+ externalize?: string;
4
+ }>;
5
+ interface ModuleCache {
6
+ promise?: Promise<any>;
7
+ exports?: any;
8
+ code?: string;
9
+ }
10
+ interface ViteNodeRunnerOptions {
11
+ fetchModule: FetchFunction;
12
+ root: string;
13
+ base?: string;
14
+ moduleCache?: Map<string, ModuleCache>;
15
+ interpretDefault?: boolean;
16
+ requestStubs?: Record<string, any>;
17
+ }
18
+
19
+ declare class ViteNodeRunner {
20
+ options: ViteNodeRunnerOptions;
21
+ root: string;
22
+ externalCache: Map<string, string | Promise<false | string>>;
23
+ moduleCache: Map<string, ModuleCache>;
24
+ constructor(options: ViteNodeRunnerOptions);
25
+ run(file: string): Promise<any>;
26
+ cachedRequest(rawId: string, callstack: string[]): Promise<any>;
27
+ directRequest(id: string, fsPath: string, callstack: string[]): Promise<any>;
28
+ prepareContext(context: Record<string, any>): Record<string, any>;
29
+ setCache(id: string, mod: Partial<ModuleCache>): void;
30
+ }
31
+
32
+ export { ViteNodeRunner };
package/dist/client.js ADDED
@@ -0,0 +1,138 @@
1
+ import { builtinModules, createRequire } from 'module';
2
+ import { pathToFileURL, fileURLToPath } from 'url';
3
+ import vm from 'vm';
4
+ import { resolve, dirname } from 'pathe';
5
+ import { slash, normalizeId, toFilePath } from './utils.js';
6
+
7
+ class ViteNodeRunner {
8
+ constructor(options) {
9
+ this.options = options;
10
+ this.root = options.root || process.cwd();
11
+ this.moduleCache = options.moduleCache || new Map();
12
+ this.externalCache = new Map();
13
+ builtinModules.forEach((m) => this.externalCache.set(m, m));
14
+ }
15
+ async run(file) {
16
+ return await this.cachedRequest(`/@fs/${slash(resolve(file))}`, []);
17
+ }
18
+ async cachedRequest(rawId, callstack) {
19
+ var _a, _b;
20
+ const id = normalizeId(rawId, this.options.base);
21
+ const fsPath = toFilePath(id, this.root);
22
+ if ((_a = this.moduleCache.get(fsPath)) == null ? void 0 : _a.promise)
23
+ return (_b = this.moduleCache.get(fsPath)) == null ? void 0 : _b.promise;
24
+ const promise = this.directRequest(id, fsPath, callstack);
25
+ this.setCache(fsPath, { promise });
26
+ return await promise;
27
+ }
28
+ async directRequest(id, fsPath, callstack) {
29
+ callstack = [...callstack, id];
30
+ const request = async (dep) => {
31
+ var _a;
32
+ if (callstack.includes(dep)) {
33
+ const cacheKey = toFilePath(dep, this.root);
34
+ if (!((_a = this.moduleCache.get(cacheKey)) == null ? void 0 : _a.exports))
35
+ throw new Error(`Circular dependency detected
36
+ Stack:
37
+ ${[...callstack, dep].reverse().map((p) => `- ${p}`).join("\n")}`);
38
+ return this.moduleCache.get(cacheKey).exports;
39
+ }
40
+ return this.cachedRequest(dep, callstack);
41
+ };
42
+ if (this.options.requestStubs && id in this.options.requestStubs)
43
+ return this.options.requestStubs[id];
44
+ const { code: transformed, externalize } = await this.options.fetchModule(id);
45
+ if (externalize) {
46
+ const mod = await interpretedImport(externalize, this.options.interpretDefault ?? true);
47
+ this.setCache(fsPath, { exports: mod });
48
+ return mod;
49
+ }
50
+ if (transformed == null)
51
+ throw new Error(`failed to load ${id}`);
52
+ const url = pathToFileURL(fsPath).href;
53
+ const exports = {};
54
+ this.setCache(fsPath, { code: transformed, exports });
55
+ const __filename = fileURLToPath(url);
56
+ const moduleProxy = {
57
+ set exports(value) {
58
+ exportAll(exports, value);
59
+ exports.default = value;
60
+ },
61
+ get exports() {
62
+ return exports.default;
63
+ }
64
+ };
65
+ const context = this.prepareContext({
66
+ __vite_ssr_import__: request,
67
+ __vite_ssr_dynamic_import__: request,
68
+ __vite_ssr_exports__: exports,
69
+ __vite_ssr_exportAll__: (obj) => exportAll(exports, obj),
70
+ __vite_ssr_import_meta__: { url },
71
+ require: createRequire(url),
72
+ exports,
73
+ module: moduleProxy,
74
+ __filename,
75
+ __dirname: dirname(__filename)
76
+ });
77
+ const fn = vm.runInThisContext(`async (${Object.keys(context).join(",")})=>{{${transformed}
78
+ }}`, {
79
+ filename: fsPath,
80
+ lineOffset: 0
81
+ });
82
+ await fn(...Object.values(context));
83
+ return exports;
84
+ }
85
+ prepareContext(context) {
86
+ return context;
87
+ }
88
+ setCache(id, mod) {
89
+ if (!this.moduleCache.has(id))
90
+ this.moduleCache.set(id, mod);
91
+ else
92
+ Object.assign(this.moduleCache.get(id), mod);
93
+ }
94
+ }
95
+ function hasNestedDefault(target) {
96
+ return "__esModule" in target && target.__esModule && "default" in target.default;
97
+ }
98
+ function proxyMethod(name, tryDefault) {
99
+ return function(target, key, ...args) {
100
+ const result = Reflect[name](target, key, ...args);
101
+ if (typeof target.default !== "object")
102
+ return result;
103
+ if (tryDefault && key === "default" || typeof result === "undefined")
104
+ return Reflect[name](target.default, key, ...args);
105
+ return result;
106
+ };
107
+ }
108
+ async function interpretedImport(path, interpretDefault) {
109
+ const mod = await import(path);
110
+ if (interpretDefault && "default" in mod) {
111
+ const tryDefault = hasNestedDefault(mod);
112
+ return new Proxy(mod, {
113
+ get: proxyMethod("get", tryDefault),
114
+ set: proxyMethod("set", tryDefault),
115
+ has: proxyMethod("has", tryDefault),
116
+ deleteProperty: proxyMethod("deleteProperty", tryDefault)
117
+ });
118
+ }
119
+ return mod;
120
+ }
121
+ function exportAll(exports, sourceModule) {
122
+ for (const key in sourceModule) {
123
+ if (key !== "default") {
124
+ try {
125
+ Object.defineProperty(exports, key, {
126
+ enumerable: true,
127
+ configurable: true,
128
+ get() {
129
+ return sourceModule[key];
130
+ }
131
+ });
132
+ } catch (_err) {
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ export { ViteNodeRunner };
@@ -0,0 +1,31 @@
1
+ interface ExternalizeOptions {
2
+ external?: (string | RegExp)[];
3
+ inline?: (string | RegExp)[];
4
+ fallbackCJS?: boolean;
5
+ }
6
+ declare type FetchFunction = (id: string) => Promise<{
7
+ code?: string;
8
+ externalize?: string;
9
+ }>;
10
+ interface ModuleCache {
11
+ promise?: Promise<any>;
12
+ exports?: any;
13
+ code?: string;
14
+ }
15
+ interface ViteNodeRunnerOptions {
16
+ fetchModule: FetchFunction;
17
+ root: string;
18
+ base?: string;
19
+ moduleCache?: Map<string, ModuleCache>;
20
+ interpretDefault?: boolean;
21
+ requestStubs?: Record<string, any>;
22
+ }
23
+ interface ViteNodeServerOptions {
24
+ deps?: ExternalizeOptions;
25
+ transformMode?: {
26
+ ssr?: RegExp[];
27
+ web?: RegExp[];
28
+ };
29
+ }
30
+
31
+ export { ExternalizeOptions, FetchFunction, ModuleCache, ViteNodeRunnerOptions, ViteNodeServerOptions };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,38 @@
1
+ import { ViteDevServer, TransformResult } from 'vite';
2
+
3
+ interface ExternalizeOptions {
4
+ external?: (string | RegExp)[];
5
+ inline?: (string | RegExp)[];
6
+ fallbackCJS?: boolean;
7
+ }
8
+ interface ViteNodeServerOptions {
9
+ deps?: ExternalizeOptions;
10
+ transformMode?: {
11
+ ssr?: RegExp[];
12
+ web?: RegExp[];
13
+ };
14
+ }
15
+
16
+ declare function guessCJSversion(id: string): string | undefined;
17
+ declare function shouldExternalize(id: string, config?: ExternalizeOptions, cache?: Map<string, Promise<string | false>>): Promise<string | false>;
18
+
19
+ declare class ViteNodeServer {
20
+ server: ViteDevServer;
21
+ options: ViteNodeServerOptions;
22
+ promiseMap: Map<string, Promise<TransformResult | null | undefined>>;
23
+ constructor(server: ViteDevServer, options?: ViteNodeServerOptions);
24
+ shouldExternalize(id: string): Promise<string | false>;
25
+ fetchModule(id: string): Promise<{
26
+ externalize: string;
27
+ code?: undefined;
28
+ } | {
29
+ code: string | undefined;
30
+ externalize?: undefined;
31
+ }>;
32
+ transformRequest(id: string): Promise<TransformResult | null | undefined>;
33
+ private getTransformMode;
34
+ private _transformRequest;
35
+ }
36
+ declare function withInlineSourcemap(result: TransformResult): Promise<TransformResult>;
37
+
38
+ export { ViteNodeServer, guessCJSversion, shouldExternalize, withInlineSourcemap };
package/dist/server.js ADDED
@@ -0,0 +1,155 @@
1
+ import { existsSync } from 'fs';
2
+ import { isNodeBuiltin, isValidNodeImport } from 'mlly';
3
+ import { slash, toFilePath } from './utils.js';
4
+ import 'url';
5
+ import 'pathe';
6
+
7
+ const ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/;
8
+ const ESM_FOLDER_RE = /\/esm\/(.*\.js)$/;
9
+ const defaultInline = [
10
+ /\/vitest\/dist\//,
11
+ /vitest-virtual-\w+\/dist/,
12
+ /virtual:/,
13
+ /\.ts$/,
14
+ ESM_EXT_RE,
15
+ ESM_FOLDER_RE
16
+ ];
17
+ const depsExternal = [
18
+ /\.cjs.js$/,
19
+ /\.mjs$/
20
+ ];
21
+ function guessCJSversion(id) {
22
+ if (id.match(ESM_EXT_RE)) {
23
+ for (const i of [
24
+ id.replace(ESM_EXT_RE, ".mjs"),
25
+ id.replace(ESM_EXT_RE, ".umd.js"),
26
+ id.replace(ESM_EXT_RE, ".cjs.js"),
27
+ id.replace(ESM_EXT_RE, ".js")
28
+ ]) {
29
+ if (existsSync(i))
30
+ return i;
31
+ }
32
+ }
33
+ if (id.match(ESM_FOLDER_RE)) {
34
+ for (const i of [
35
+ id.replace(ESM_FOLDER_RE, "/umd/$1"),
36
+ id.replace(ESM_FOLDER_RE, "/cjs/$1"),
37
+ id.replace(ESM_FOLDER_RE, "/$1")
38
+ ]) {
39
+ if (existsSync(i))
40
+ return i;
41
+ }
42
+ }
43
+ }
44
+ async function shouldExternalize(id, config, cache = new Map()) {
45
+ if (!cache.has(id))
46
+ cache.set(id, _shouldExternalize(id, config));
47
+ return cache.get(id);
48
+ }
49
+ async function _shouldExternalize(id, config) {
50
+ if (isNodeBuiltin(id))
51
+ return id;
52
+ id = patchWindowsImportPath(id);
53
+ if (matchExternalizePattern(id, config == null ? void 0 : config.inline))
54
+ return false;
55
+ if (matchExternalizePattern(id, config == null ? void 0 : config.external))
56
+ return id;
57
+ const isNodeModule = id.includes("/node_modules/");
58
+ id = isNodeModule ? guessCJSversion(id) || id : id;
59
+ if (matchExternalizePattern(id, defaultInline))
60
+ return false;
61
+ if (matchExternalizePattern(id, depsExternal))
62
+ return id;
63
+ if (isNodeModule && await isValidNodeImport(id))
64
+ return id;
65
+ return false;
66
+ }
67
+ function matchExternalizePattern(id, patterns) {
68
+ if (!patterns)
69
+ return false;
70
+ for (const ex of patterns) {
71
+ if (typeof ex === "string") {
72
+ if (id.includes(`/node_modules/${ex}/`))
73
+ return true;
74
+ } else {
75
+ if (ex.test(id))
76
+ return true;
77
+ }
78
+ }
79
+ return false;
80
+ }
81
+ function patchWindowsImportPath(path) {
82
+ if (path.match(/^\w:\\/))
83
+ return `file:///${slash(path)}`;
84
+ else if (path.match(/^\w:\//))
85
+ return `file:///${path}`;
86
+ else
87
+ return path;
88
+ }
89
+
90
+ let SOURCEMAPPING_URL = "sourceMa";
91
+ SOURCEMAPPING_URL += "ppingURL";
92
+ class ViteNodeServer {
93
+ constructor(server, options = {}) {
94
+ this.server = server;
95
+ this.options = options;
96
+ this.promiseMap = new Map();
97
+ }
98
+ shouldExternalize(id) {
99
+ return shouldExternalize(id, this.options.deps);
100
+ }
101
+ async fetchModule(id) {
102
+ const externalize = await this.shouldExternalize(toFilePath(id, this.server.config.root));
103
+ if (externalize)
104
+ return { externalize };
105
+ const r = await this.transformRequest(id);
106
+ return { code: r == null ? void 0 : r.code };
107
+ }
108
+ async transformRequest(id) {
109
+ if (!this.promiseMap.has(id)) {
110
+ this.promiseMap.set(id, this._transformRequest(id).then((r) => {
111
+ this.promiseMap.delete(id);
112
+ return r;
113
+ }));
114
+ }
115
+ return this.promiseMap.get(id);
116
+ }
117
+ getTransformMode(id) {
118
+ var _a, _b, _c, _d;
119
+ const withoutQuery = id.split("?")[0];
120
+ if ((_b = (_a = this.options.transformMode) == null ? void 0 : _a.web) == null ? void 0 : _b.some((r) => withoutQuery.match(r)))
121
+ return "web";
122
+ if ((_d = (_c = this.options.transformMode) == null ? void 0 : _c.ssr) == null ? void 0 : _d.some((r) => withoutQuery.match(r)))
123
+ return "ssr";
124
+ if (withoutQuery.match(/\.([cm]?[jt]sx?|json)$/))
125
+ return "ssr";
126
+ return "web";
127
+ }
128
+ async _transformRequest(id) {
129
+ let result = null;
130
+ const mode = this.getTransformMode(id);
131
+ if (mode === "web") {
132
+ result = await this.server.transformRequest(id);
133
+ if (result)
134
+ result = await this.server.ssrTransform(result.code, result.map, id);
135
+ } else {
136
+ result = await this.server.transformRequest(id, { ssr: true });
137
+ }
138
+ if (result && !id.includes("node_modules"))
139
+ withInlineSourcemap(result);
140
+ return result;
141
+ }
142
+ }
143
+ async function withInlineSourcemap(result) {
144
+ const { code, map } = result;
145
+ if (code.includes(`${SOURCEMAPPING_URL}=`))
146
+ return result;
147
+ if (map)
148
+ result.code = `${code}
149
+
150
+ //# ${SOURCEMAPPING_URL}=data:application/json;charset=utf-8;base64,${Buffer.from(JSON.stringify(map), "utf-8").toString("base64")}
151
+ `;
152
+ return result;
153
+ }
154
+
155
+ export { ViteNodeServer, guessCJSversion, shouldExternalize, withInlineSourcemap };
@@ -0,0 +1,6 @@
1
+ declare const isWindows: boolean;
2
+ declare function slash(str: string): string;
3
+ declare function normalizeId(id: string, base?: string): string;
4
+ declare function toFilePath(id: string, root: string): string;
5
+
6
+ export { isWindows, normalizeId, slash, toFilePath };
package/dist/utils.js ADDED
@@ -0,0 +1,20 @@
1
+ import { fileURLToPath, pathToFileURL } from 'url';
2
+ import { dirname, resolve } from 'pathe';
3
+
4
+ const isWindows = process.platform === "win32";
5
+ function slash(str) {
6
+ return str.replace(/\\/g, "/");
7
+ }
8
+ function normalizeId(id, base) {
9
+ if (base && id.startsWith(base))
10
+ id = `/${id.slice(base.length)}`;
11
+ return id.replace(/^\/@id\/__x00__/, "\0").replace(/^\/@id\//, "").replace(/^__vite-browser-external:/, "").replace(/^node:/, "").replace(/[?&]v=\w+/, "?").replace(/\?$/, "");
12
+ }
13
+ function toFilePath(id, root) {
14
+ let absolute = slash(id).startsWith("/@fs/") ? id.slice(4) : id.startsWith(dirname(root)) ? id : id.startsWith("/") ? slash(resolve(root, id.slice(1))) : id;
15
+ if (absolute.startsWith("//"))
16
+ absolute = absolute.slice(1);
17
+ return isWindows && absolute.startsWith("/") ? fileURLToPath(pathToFileURL(absolute.slice(1)).href) : absolute;
18
+ }
19
+
20
+ export { isWindows, normalizeId, slash, toFilePath };
package/package.json CHANGED
@@ -1,63 +1,67 @@
1
1
  {
2
2
  "name": "vite-node",
3
- "version": "0.0.5",
4
- "description": "Vite as Node runtime",
5
- "keywords": [
6
- "vite"
7
- ],
8
- "homepage": "https://github.com/antfu/vite-node#readme",
3
+ "version": "0.0.140",
4
+ "description": "Vite as Node.js runtime",
5
+ "homepage": "https://github.com/vitest-dev/vitest#readme",
9
6
  "bugs": {
10
- "url": "https://github.com/antfu/vite-node/issues"
7
+ "url": "https://github.com/vitest-dev/vitest/issues"
11
8
  },
12
9
  "repository": {
13
10
  "type": "git",
14
- "url": "git+https://github.com/antfu/vite-node.git"
11
+ "url": "git+https://github.com/vitest-dev/vitest.git",
12
+ "directory": "packages/vite-node"
15
13
  },
16
14
  "funding": "https://github.com/sponsors/antfu",
17
15
  "license": "MIT",
18
16
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
19
- "sideEffects": false,
20
17
  "type": "module",
21
18
  "exports": {
22
19
  ".": {
23
- "import": "./index.mjs"
20
+ "import": "./dist/index.js",
21
+ "types": "./dist/index.d.ts"
22
+ },
23
+ "./client": {
24
+ "import": "./dist/client.js",
25
+ "types": "./dist/client.d.ts"
26
+ },
27
+ "./server": {
28
+ "import": "./dist/server.js",
29
+ "types": "./dist/server.d.ts"
30
+ },
31
+ "./utils": {
32
+ "import": "./dist/utils.js",
33
+ "types": "./dist/utils.d.ts"
24
34
  }
25
35
  },
26
- "main": "index.mjs",
27
- "module": "index.mjs",
36
+ "main": "./dist/index.js",
37
+ "module": "./dist/index.js",
38
+ "types": "./dist/index.d.ts",
28
39
  "bin": {
29
- "vite-node": "./bin/vite-node.js"
40
+ "vite-node": "./vite-node.js"
30
41
  },
31
42
  "files": [
32
- "index.mjs",
33
- "bin"
43
+ "dist",
44
+ "*.d.ts",
45
+ "*.mjs"
34
46
  ],
35
47
  "dependencies": {
36
- "debug": "^4.3.2",
37
- "kolorist": "^1.5.0",
48
+ "kolorist": "^1.5.1",
38
49
  "minimist": "^1.2.5",
39
- "vite": "^2.6.5"
50
+ "mlly": "^0.3.17",
51
+ "pathe": "^0.2.0",
52
+ "vite": "^2.7.10"
40
53
  },
41
54
  "devDependencies": {
42
- "@antfu/eslint-config": "^0.9.0",
43
- "@antfu/ni": "^0.10.0",
44
- "@types/debug": "^4.1.7",
45
- "@types/node": "^16.10.3",
46
- "@vitejs/plugin-vue": "^1.9.3",
47
- "bumpp": "^7.1.1",
48
- "eslint": "^7.32.0",
49
- "esno": "^0.10.1",
50
- "typescript": "^4.4.3",
51
- "uvu": "^0.5.2",
52
- "vue": "^3.2.20"
55
+ "@types/minimist": "^1.2.2",
56
+ "rollup": "^2.63.0"
53
57
  },
54
58
  "engines": {
55
- "node": ">=14.0.0"
59
+ "node": ">=14.14.0"
56
60
  },
57
61
  "scripts": {
58
- "lint": "eslint \"**/*.{ts,mjs}\"",
59
- "release": "bumpp --commit --push --tag && pnpm publish",
60
- "start": "DEBUG=vite-node:* node index.mjs",
61
- "test": "node index.mjs -c test/vite.config.ts --vue test/index.test.mjs"
62
- }
62
+ "build": "rimraf dist && rollup -c",
63
+ "dev": "rollup -c --watch --watch.include=src/**",
64
+ "typecheck": "tsc --noEmit"
65
+ },
66
+ "readme": "# vite-node\n\n[![NPM version](https://img.shields.io/npm/v/vite-node?color=a1b858&label=)](https://www.npmjs.com/package/vite-node)\n\nVite as Node runtime. The engine powers [Vitest](https://github.com/vitest-dev/vitest).\n\n## Features\n\n- Out-of-box ESM & TypeScript support (possible for more with plugins)\n- Top-level await\n- Vite plugins, resolve, aliasing\n- Respect `vite.config.ts`\n- Shims for `__dirname` and `__filename` in ESM\n- Access to native node modules like `fs`, `path`, etc.\n\n## CLI Usage\n\nRun JS/TS file on Node.js using Vite's resolvers and transformers.\n\n```bash\nnpx vite-node index.ts\n```\n\nOptions:\n\n```bash\nnpx vite-node -h\n```\n\n## Programmatic Usage\n\nIn Vite Node, the server and runner (client) are separated, so you can integrate them in different contexts (workers, cross-process, or remote) if needed. The demo below shows a simple example of having the server and running in the same context\n\n```ts\nimport { createServer } from 'vite'\nimport { ViteNodeServer } from 'vite-node/server'\nimport { ViteNodeRunner } from 'vite-node/client'\n\n// create vite server\nconst server = await createServer()\n// this is need to initialize the plugins\nawait server.pluginContainer.buildStart({})\n\n// create vite-node server\nconst node = new ViteNodeServer(server)\n\n// create vite-node runner\nconst runner = new ViteNodeRunner({\n root: server.config.root,\n base: server.config.base,\n // when having the server and runner in a different context,\n // you will need to handle the communication between them\n // and pass to this function\n fetchModule(id) {\n return node.fetchModule(id)\n },\n})\n\n// execute the file\nawait runner.run('./example.ts')\n\n// close the vite server\nawait server.close()\n```\n\n## Credits\n\nBased on [@pi0](https://github.com/pi0)'s brilliant idea of having a Vite server as the on-demand transforming service for [Nuxt's Vite SSR](https://github.com/nuxt/vite/pull/201).\n\nThanks [@brillout](https://github.com/brillout) for kindly sharing this package name.\n\n## Sponsors\n\n<p align=\"center\">\n <a href=\"https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg\">\n <img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>\n </a>\n</p>\n\n## License\n\n[MIT](./LICENSE) License © 2021 [Anthony Fu](https://github.com/antfu)\n"
63
67
  }
package/vite-node.mjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import('./dist/cli.js')
package/bin/vite-node.js DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict'
3
-
4
- import '../index.mjs'
package/index.mjs DELETED
@@ -1,244 +0,0 @@
1
- /* eslint-disable no-console */
2
- import { builtinModules, createRequire } from 'module'
3
- import { pathToFileURL } from 'url'
4
- import { dirname, resolve, relative } from 'path'
5
- import { createServer } from 'vite'
6
- import createDebug from 'debug'
7
- import minimist from 'minimist'
8
- import { red, dim, yellow, green, inverse, cyan } from 'kolorist'
9
-
10
- const argv = minimist(process.argv.slice(2), {
11
- alias: {
12
- r: 'root',
13
- c: 'config',
14
- h: 'help',
15
- w: 'watch',
16
- s: 'silent',
17
- },
18
- string: ['root', 'config'],
19
- boolean: ['help', 'vue', 'watch', 'silent'],
20
- unknown(name) {
21
- if (name[0] === '-') {
22
- console.error(red(`Unknown argument: ${name}`))
23
- help()
24
- process.exit(1)
25
- }
26
- },
27
- })
28
- const files = argv._
29
-
30
- if (argv.help) {
31
- help()
32
- process.exit(0)
33
- }
34
-
35
- if (!argv._.length) {
36
- console.error(red('No files specified.'))
37
- help()
38
- process.exit(1)
39
- }
40
-
41
- const debugRequest = createDebug('vite-node:request')
42
- const debugTransform = createDebug('vite-node:transform')
43
- const AsyncFunction = Object.getPrototypeOf(async() => {}).constructor
44
-
45
- const root = argv.root || process.cwd()
46
- process.chdir(root)
47
-
48
- const server = await createServer({
49
- logLevel: 'error',
50
- clearScreen: false,
51
- configFile: argv.config,
52
- root,
53
- resolve: argv.vue
54
- ? {
55
- alias: {
56
- // fix for Vue does not support mjs yet
57
- 'vue/server-renderer': 'vue/server-renderer',
58
- 'vue/compiler-sfc': 'vue/compiler-sfc',
59
- '@vue/reactivity': '@vue/reactivity/dist/reactivity.cjs.js',
60
- '@vue/shared': '@vue/shared/dist/shared.cjs.js',
61
- 'vue-router': 'vue-router/dist/vue-router.cjs.js',
62
- 'vue': 'vue/dist/vue.cjs.js',
63
- },
64
- }
65
- : {},
66
- })
67
- await server.pluginContainer.buildStart({})
68
- let executing = false
69
-
70
- async function run() {
71
- process.exitCode = 0
72
- executing = true
73
- let err
74
- try {
75
- await execute(files, server, argv)
76
- }
77
- catch (e) {
78
- console.error(e)
79
- err = e
80
- if (!argv.watch)
81
- process.exit(1)
82
- }
83
- finally {
84
- executing = false
85
- }
86
-
87
- if (argv.watch) {
88
- setTimeout(() => {
89
- if (err || process.exitCode)
90
- log(inverse(red(' vite node ')), red('program exited with error, waiting for file changes...'))
91
- else
92
- log(inverse(green(' vite node ')), green('program exited, waiting for file changes...'))
93
- }, 10)
94
- }
95
- else {
96
- await server.close()
97
- }
98
- }
99
-
100
- if (argv.watch) {
101
- log(inverse(cyan(' vite node ')), cyan('watch mode enabled\n'))
102
-
103
- server.watcher.on('change', (file) => {
104
- if (!executing) {
105
- log(inverse(yellow(' vite node ')), yellow(`${file} changed, restarting...\n`))
106
- run()
107
- }
108
- })
109
- }
110
-
111
- await run(files, server, argv)
112
-
113
- // --- CLI END ---
114
-
115
- function normalizeId(id) {
116
- // Virtual modules start with `\0`
117
- if (id && id.startsWith('/@id/__x00__'))
118
- id = `\0${id.slice('/@id/__x00__'.length)}`
119
- if (id && id.startsWith('/@id/'))
120
- id = id.slice('/@id/'.length)
121
- return id
122
- }
123
-
124
- function toFilePath(id) {
125
- const absolute = id.startsWith('/@fs/')
126
- ? id.slice(4)
127
- : slash(resolve(server.config.root, id.slice(1)))
128
-
129
- return absolute
130
- }
131
-
132
- async function execute(files, server) {
133
- const __pendingModules__ = new Map()
134
-
135
- const result = []
136
- for (const file of files)
137
- result.push(await cachedRequest(`/@fs/${slash(resolve(file))}`, []))
138
- return result
139
-
140
- async function directRequest(rawId, callstack) {
141
- if (builtinModules.includes(rawId))
142
- return import(rawId)
143
-
144
- callstack = [...callstack, rawId]
145
- const request = async(dep) => {
146
- if (callstack.includes(dep)) {
147
- throw new Error(`${red('Circular dependency detected')}\nStack:\n${[...callstack, dep].reverse().map((i) => {
148
- const path = relative(server.config.root, toFilePath(normalizeId(i)))
149
- return dim(' -> ') + (i === dep ? yellow(path) : path)
150
- }).join('\n')}\n`)
151
- }
152
- return cachedRequest(dep, callstack)
153
- }
154
-
155
- const id = normalizeId(rawId)
156
- const absolute = toFilePath(id)
157
-
158
- debugRequest(absolute)
159
-
160
- // for windows
161
- const unifiedPath = absolute[0] !== '/'
162
- ? `/${absolute}`
163
- : absolute
164
-
165
- if (absolute.includes('/node_modules/'))
166
- return import(unifiedPath)
167
-
168
- const result = await server.transformRequest(id, { ssr: true })
169
- if (!result)
170
- throw new Error(`failed to load ${id}`)
171
-
172
- debugTransform(id, result.code)
173
-
174
- const url = pathToFileURL(unifiedPath)
175
- const exports = {}
176
-
177
- const context = {
178
- require: createRequire(url),
179
- __filename: absolute,
180
- __dirname: dirname(absolute),
181
- __vite_ssr_import__: request,
182
- __vite_ssr_dynamic_import__: request,
183
- __vite_ssr_exports__: exports,
184
- __vite_ssr_exportAll__: obj => exportAll(exports, obj),
185
- __vite_ssr_import_meta__: { url },
186
- }
187
-
188
- const fn = new AsyncFunction(
189
- ...Object.keys(context),
190
- result.code,
191
- )
192
-
193
- // prefetch deps
194
- await fn(...Object.values(context))
195
-
196
- return exports
197
- }
198
-
199
- function cachedRequest(id, callstack) {
200
- if (!__pendingModules__[id])
201
- __pendingModules__[id] = directRequest(id, callstack)
202
- return __pendingModules__[id]
203
- }
204
-
205
- function exportAll(exports, sourceModule) {
206
- // eslint-disable-next-line no-restricted-syntax
207
- for (const key in sourceModule) {
208
- if (key !== 'default') {
209
- try {
210
- Object.defineProperty(exports, key, {
211
- enumerable: true,
212
- configurable: true,
213
- get() { return sourceModule[key] },
214
- })
215
- }
216
- catch (_err) { }
217
- }
218
- }
219
- }
220
- }
221
-
222
- function slash(path) {
223
- return path.replace(/\\/g, '/')
224
- }
225
-
226
- function help() {
227
- console.log(`
228
- Usage:
229
- $ vite-node [options] [files]
230
-
231
- Options:
232
- -r, --root <path> ${dim('[string]')} use specified root directory
233
- -c, --config <file> ${dim('[string]')} use specified config file
234
- -w, --watch ${dim('[boolean]')} restart on file changes, similar to "nodemon"
235
- -s, --silent ${dim('[boolean]')} do not emit errors and logs
236
- --vue ${dim('[boolean]')} support for importing Vue component
237
- `)
238
- }
239
-
240
- function log(...args) {
241
- if (argv.silent)
242
- return
243
- console.log(...args)
244
- }