@vercel/cervel 0.0.10 → 0.0.11
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/dist/cli.mjs +267 -39
- package/dist/index.d.mts +42 -13
- package/dist/index.mjs +264 -39
- package/package.json +8 -3
package/dist/cli.mjs
CHANGED
|
@@ -1,23 +1,244 @@
|
|
|
1
|
+
import { builtinModules, createRequire } from "node:module";
|
|
1
2
|
import { parseArgs } from "node:util";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { extname, join } from "path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { lstat, readFile, rm } from "node:fs/promises";
|
|
5
|
+
import { dirname, extname, join, relative } from "node:path";
|
|
6
6
|
import { build } from "rolldown";
|
|
7
|
+
import { exports } from "resolve.exports";
|
|
8
|
+
import { isNativeError } from "node:util/types";
|
|
9
|
+
import { FileFsRef, debug, glob } from "@vercel/build-utils";
|
|
10
|
+
import { nodeFileTrace, resolve } from "@vercel/nft";
|
|
11
|
+
import { transform } from "oxc-transform";
|
|
12
|
+
import { createRequire as createRequire$1 } from "module";
|
|
7
13
|
import { spawn } from "child_process";
|
|
14
|
+
import { extname as extname$1, join as join$1 } from "path";
|
|
15
|
+
import { existsSync as existsSync$1 } from "fs";
|
|
8
16
|
import execa from "execa";
|
|
17
|
+
import { writeFile } from "fs/promises";
|
|
9
18
|
|
|
19
|
+
//#region src/node-file-trace.ts
|
|
20
|
+
const nodeFileTrace$1 = async (args) => {
|
|
21
|
+
const files = {};
|
|
22
|
+
const { tracedPaths } = args;
|
|
23
|
+
const compiledSourceFiles = await glob("**/*", {
|
|
24
|
+
cwd: args.outDir,
|
|
25
|
+
follow: true,
|
|
26
|
+
includeDirectories: true
|
|
27
|
+
});
|
|
28
|
+
for (const file of Object.keys(compiledSourceFiles)) files[file] = compiledSourceFiles[file];
|
|
29
|
+
/**
|
|
30
|
+
* While we're not using NFT to process source code, we are using it
|
|
31
|
+
* to tree shake node deps, and include any fs reads for files that are
|
|
32
|
+
* not part of the traced paths or compiled source files.
|
|
33
|
+
* Most of this is identical to the `@vercel/node` implementation
|
|
34
|
+
*/
|
|
35
|
+
const result = await nodeFileTrace(Array.from(tracedPaths), {
|
|
36
|
+
base: args.repoRootPath,
|
|
37
|
+
processCwd: args.workPath,
|
|
38
|
+
ts: true,
|
|
39
|
+
mixedModules: true,
|
|
40
|
+
async resolve(id, parent, job, cjsResolve) {
|
|
41
|
+
return resolve(id, parent, job, cjsResolve);
|
|
42
|
+
},
|
|
43
|
+
async readFile(fsPath) {
|
|
44
|
+
try {
|
|
45
|
+
let source = await readFile(fsPath);
|
|
46
|
+
if (fsPath.endsWith(".ts") && !fsPath.endsWith(".d.ts") || fsPath.endsWith(".tsx") || fsPath.endsWith(".mts") || fsPath.endsWith(".cts")) source = (await transform(fsPath, source.toString())).code;
|
|
47
|
+
return source;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (isNativeError(error) && "code" in error && (error.code === "ENOENT" || error.code === "EISDIR")) return null;
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
if (!args.keepTracedPaths) for (const file of tracedPaths) {
|
|
55
|
+
const relativeFile = relative(args.repoRootPath, file);
|
|
56
|
+
result.fileList.delete(relativeFile);
|
|
57
|
+
}
|
|
58
|
+
debug("NFT traced files count:", result.fileList.size);
|
|
59
|
+
for (const file of result.fileList) {
|
|
60
|
+
const absolutePath = join(args.repoRootPath, file);
|
|
61
|
+
const stats = await lstat(absolutePath);
|
|
62
|
+
const outputPath = file;
|
|
63
|
+
if (stats.isSymbolicLink() || stats.isFile()) files[outputPath] = new FileFsRef({
|
|
64
|
+
fsPath: absolutePath,
|
|
65
|
+
mode: stats.mode
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
debug("Total files in context:", Object.keys(files).length);
|
|
69
|
+
return files;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/plugin.ts
|
|
74
|
+
const CJS_SHIM_PREFIX = "\0cjs-shim:";
|
|
75
|
+
const plugin = (args) => {
|
|
76
|
+
const packageJsonCache = /* @__PURE__ */ new Map();
|
|
77
|
+
const shimMeta = /* @__PURE__ */ new Map();
|
|
78
|
+
const tracedPaths = /* @__PURE__ */ new Set();
|
|
79
|
+
const isBareImport = (id) => {
|
|
80
|
+
return !id.startsWith(".") && !id.startsWith("/") && !/^[a-z][a-z0-9+.-]*:/i.test(id);
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Read and cache package.json contents
|
|
84
|
+
*/
|
|
85
|
+
const getPackageJson = async (pkgPath) => {
|
|
86
|
+
if (packageJsonCache.has(pkgPath)) return packageJsonCache.get(pkgPath);
|
|
87
|
+
try {
|
|
88
|
+
const contents = await readFile(pkgPath, "utf-8");
|
|
89
|
+
const parsed = JSON.parse(contents);
|
|
90
|
+
packageJsonCache.set(pkgPath, parsed);
|
|
91
|
+
return parsed;
|
|
92
|
+
} catch {
|
|
93
|
+
packageJsonCache.set(pkgPath, null);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Determine if a resolved module is CommonJS based on package.json exports
|
|
99
|
+
*/
|
|
100
|
+
const isCommonJS = async (bareImport, resolvedPath, resolvedInfo) => {
|
|
101
|
+
const ext = extname(resolvedPath);
|
|
102
|
+
if (ext === ".cjs") return true;
|
|
103
|
+
if (ext === ".mjs") return false;
|
|
104
|
+
if (ext === ".js" || ext === ".ts") {
|
|
105
|
+
const pkgJsonPath = resolvedInfo.packageJsonPath;
|
|
106
|
+
if (!pkgJsonPath) return true;
|
|
107
|
+
const pkgJson = await getPackageJson(pkgJsonPath);
|
|
108
|
+
if (!pkgJson) return true;
|
|
109
|
+
const pkgDir = dirname(pkgJsonPath);
|
|
110
|
+
const relativePath = resolvedPath.startsWith(pkgDir) ? resolvedPath.slice(pkgDir.length + 1).replace(/\\/g, "/") : null;
|
|
111
|
+
if (!relativePath) return pkgJson.type !== "module";
|
|
112
|
+
const pkgName = pkgJson.name || "";
|
|
113
|
+
const subpath = bareImport.startsWith(pkgName) ? `.${bareImport.slice(pkgName.length)}` || "." : ".";
|
|
114
|
+
try {
|
|
115
|
+
if (exports(pkgJson, subpath, {
|
|
116
|
+
require: false,
|
|
117
|
+
conditions: ["node", "import"]
|
|
118
|
+
})?.some((p) => p === relativePath || p === `./${relativePath}`)) return false;
|
|
119
|
+
if (exports(pkgJson, subpath, {
|
|
120
|
+
require: true,
|
|
121
|
+
conditions: ["node", "require"]
|
|
122
|
+
})?.some((p) => p === relativePath || p === `./${relativePath}`)) return true;
|
|
123
|
+
} catch (err) {
|
|
124
|
+
console.warn("Export resolution failed::", err);
|
|
125
|
+
}
|
|
126
|
+
if (pkgJson.module) return false;
|
|
127
|
+
return pkgJson.type !== "module";
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
131
|
+
const isLocalImport = (id) => {
|
|
132
|
+
if (id.startsWith("node:")) return false;
|
|
133
|
+
if (id.includes("node_modules")) return false;
|
|
134
|
+
return true;
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
name: "cervel",
|
|
138
|
+
resolveId: {
|
|
139
|
+
order: "pre",
|
|
140
|
+
async handler(id, importer, rOpts) {
|
|
141
|
+
if (id.startsWith(CJS_SHIM_PREFIX)) return {
|
|
142
|
+
id,
|
|
143
|
+
external: false
|
|
144
|
+
};
|
|
145
|
+
const resolved = await this.resolve(id, importer, rOpts);
|
|
146
|
+
if (builtinModules.includes(id)) return {
|
|
147
|
+
id: `node:${id}`,
|
|
148
|
+
external: true
|
|
149
|
+
};
|
|
150
|
+
if (resolved?.id && isLocalImport(resolved.id)) tracedPaths.add(resolved.id);
|
|
151
|
+
if (importer?.startsWith(CJS_SHIM_PREFIX) && isBareImport(id)) return {
|
|
152
|
+
id,
|
|
153
|
+
external: true
|
|
154
|
+
};
|
|
155
|
+
if (importer && isBareImport(id) && resolved?.id?.includes("node_modules")) {
|
|
156
|
+
if (args.shimBareImports) {
|
|
157
|
+
if (await isCommonJS(id, resolved.id, resolved)) {
|
|
158
|
+
const importerPkgJsonPath = (await this.resolve(importer))?.packageJsonPath;
|
|
159
|
+
if (importerPkgJsonPath) {
|
|
160
|
+
const importerPkgDir = relative(args.repoRootPath, dirname(importerPkgJsonPath));
|
|
161
|
+
const shimId$1 = `${CJS_SHIM_PREFIX}${importerPkgDir.replace(/\//g, "_")}_${id.replace(/\//g, "_")}`;
|
|
162
|
+
shimMeta.set(shimId$1, {
|
|
163
|
+
pkgDir: importerPkgDir,
|
|
164
|
+
pkgName: id
|
|
165
|
+
});
|
|
166
|
+
return {
|
|
167
|
+
id: shimId$1,
|
|
168
|
+
external: false
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
const shimId = `${CJS_SHIM_PREFIX}${id.replace(/\//g, "_")}`;
|
|
172
|
+
shimMeta.set(shimId, {
|
|
173
|
+
pkgDir: "",
|
|
174
|
+
pkgName: id
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
id: shimId,
|
|
178
|
+
external: false
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
external: true,
|
|
184
|
+
id
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (importer && isBareImport(id)) return resolved;
|
|
188
|
+
return {
|
|
189
|
+
external: true,
|
|
190
|
+
...resolved,
|
|
191
|
+
id: resolved?.id || id
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
load: { async handler(id) {
|
|
196
|
+
if (id.startsWith(CJS_SHIM_PREFIX)) {
|
|
197
|
+
const meta = shimMeta.get(id);
|
|
198
|
+
if (!meta) return { code: `module.exports = require('${id.slice(10)}');` };
|
|
199
|
+
const { pkgDir, pkgName } = meta;
|
|
200
|
+
if (pkgDir) return { code: `
|
|
201
|
+
import { createRequire } from 'node:module';
|
|
202
|
+
import { fileURLToPath } from 'node:url';
|
|
203
|
+
import { dirname, join } from 'node:path';
|
|
204
|
+
|
|
205
|
+
const requireFromContext = createRequire(join(dirname(fileURLToPath(import.meta.url)), '${join("..", pkgDir, "package.json")}'));
|
|
206
|
+
module.exports = requireFromContext('${pkgName}');
|
|
207
|
+
`.trim() };
|
|
208
|
+
return { code: `module.exports = require('${pkgName}');` };
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
} },
|
|
212
|
+
writeBundle: {
|
|
213
|
+
order: "post",
|
|
214
|
+
async handler() {
|
|
215
|
+
const files = await nodeFileTrace$1({
|
|
216
|
+
outDir: args.outDir,
|
|
217
|
+
tracedPaths: Array.from(tracedPaths),
|
|
218
|
+
repoRootPath: args.repoRootPath,
|
|
219
|
+
workPath: args.workPath,
|
|
220
|
+
context: args.context,
|
|
221
|
+
keepTracedPaths: false
|
|
222
|
+
});
|
|
223
|
+
args.context.files = files;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
//#endregion
|
|
10
230
|
//#region src/rolldown.ts
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
231
|
+
const __dirname__filenameShim = `
|
|
232
|
+
import { createRequire as __createRequire } from 'node:module';
|
|
233
|
+
import { fileURLToPath as __fileURLToPath } from 'node:url';
|
|
234
|
+
import { dirname as __dirname_ } from 'node:path';
|
|
235
|
+
const require = __createRequire(import.meta.url);
|
|
236
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
237
|
+
const __dirname = __dirname_(__filename);
|
|
238
|
+
`.trim();
|
|
17
239
|
const rolldown = async (args) => {
|
|
18
|
-
const baseDir = args.repoRootPath || args.workPath;
|
|
19
240
|
const entrypointPath = join(args.workPath, args.entrypoint);
|
|
20
|
-
const
|
|
241
|
+
const outputDir = join(args.workPath, args.out);
|
|
21
242
|
const extension = extname(args.entrypoint);
|
|
22
243
|
const extensionMap = {
|
|
23
244
|
".ts": {
|
|
@@ -47,7 +268,6 @@ const rolldown = async (args) => {
|
|
|
47
268
|
};
|
|
48
269
|
const extensionInfo = extensionMap[extension] || extensionMap[".js"];
|
|
49
270
|
let resolvedFormat = extensionInfo.format === "auto" ? void 0 : extensionInfo.format;
|
|
50
|
-
const resolvedExtension = extensionInfo.extension;
|
|
51
271
|
const packageJsonPath = join(args.workPath, "package.json");
|
|
52
272
|
const external = [];
|
|
53
273
|
let pkg = {};
|
|
@@ -65,21 +285,29 @@ const rolldown = async (args) => {
|
|
|
65
285
|
for (const dependency of Object.keys(pkg.peerDependencies || {})) external.push(dependency);
|
|
66
286
|
for (const dependency of Object.keys(pkg.optionalDependencies || {})) external.push(dependency);
|
|
67
287
|
}
|
|
68
|
-
const
|
|
69
|
-
const
|
|
288
|
+
const resolvedExtension = resolvedFormat === "esm" ? "mjs" : "cjs";
|
|
289
|
+
const context = { files: {} };
|
|
70
290
|
const out = await build({
|
|
71
291
|
input: entrypointPath,
|
|
72
|
-
cwd:
|
|
292
|
+
cwd: args.workPath,
|
|
73
293
|
platform: "node",
|
|
74
294
|
tsconfig: true,
|
|
75
|
-
|
|
295
|
+
plugins: [plugin({
|
|
296
|
+
repoRootPath: args.repoRootPath,
|
|
297
|
+
outDir: outputDir,
|
|
298
|
+
workPath: args.workPath,
|
|
299
|
+
shimBareImports: resolvedFormat === "esm",
|
|
300
|
+
context
|
|
301
|
+
})],
|
|
76
302
|
output: {
|
|
77
303
|
cleanDir: true,
|
|
78
304
|
dir: outputDir,
|
|
79
305
|
format: resolvedFormat,
|
|
80
306
|
entryFileNames: `[name].${resolvedExtension}`,
|
|
81
307
|
preserveModules: true,
|
|
82
|
-
|
|
308
|
+
preserveModulesRoot: args.repoRootPath,
|
|
309
|
+
sourcemap: false,
|
|
310
|
+
banner: resolvedFormat === "esm" ? __dirname__filenameShim : void 0
|
|
83
311
|
}
|
|
84
312
|
});
|
|
85
313
|
let handler = null;
|
|
@@ -95,10 +323,9 @@ const rolldown = async (args) => {
|
|
|
95
323
|
};
|
|
96
324
|
return {
|
|
97
325
|
result: {
|
|
98
|
-
pkg,
|
|
99
|
-
shouldAddSourcemapSupport,
|
|
100
326
|
handler,
|
|
101
|
-
outputDir
|
|
327
|
+
outputDir,
|
|
328
|
+
outputFiles: context.files
|
|
102
329
|
},
|
|
103
330
|
cleanup
|
|
104
331
|
};
|
|
@@ -135,9 +362,9 @@ const Colors = {
|
|
|
135
362
|
|
|
136
363
|
//#endregion
|
|
137
364
|
//#region src/typescript.ts
|
|
138
|
-
const require_ = createRequire(import.meta.url);
|
|
365
|
+
const require_ = createRequire$1(import.meta.url);
|
|
139
366
|
const typescript = (args) => {
|
|
140
|
-
const extension = extname(args.entrypoint);
|
|
367
|
+
const extension = extname$1(args.entrypoint);
|
|
141
368
|
if (![
|
|
142
369
|
".ts",
|
|
143
370
|
".mts",
|
|
@@ -184,11 +411,11 @@ async function doTypeCheck(args, tscPath) {
|
|
|
184
411
|
child.stderr?.on("data", (data) => {
|
|
185
412
|
stderr += data.toString();
|
|
186
413
|
});
|
|
187
|
-
await new Promise((resolve, reject) => {
|
|
414
|
+
await new Promise((resolve$1, reject) => {
|
|
188
415
|
child.on("close", (code) => {
|
|
189
416
|
if (code === 0) {
|
|
190
417
|
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck complete`));
|
|
191
|
-
resolve();
|
|
418
|
+
resolve$1();
|
|
192
419
|
} else {
|
|
193
420
|
const output = stdout || stderr;
|
|
194
421
|
if (output) {
|
|
@@ -211,10 +438,10 @@ const resolveTscPath = (args) => {
|
|
|
211
438
|
}
|
|
212
439
|
};
|
|
213
440
|
const findNearestTsconfig = async (workPath) => {
|
|
214
|
-
const tsconfigPath = join(workPath, "tsconfig.json");
|
|
215
|
-
if (existsSync(tsconfigPath)) return tsconfigPath;
|
|
441
|
+
const tsconfigPath = join$1(workPath, "tsconfig.json");
|
|
442
|
+
if (existsSync$1(tsconfigPath)) return tsconfigPath;
|
|
216
443
|
if (workPath === "/") return;
|
|
217
|
-
return findNearestTsconfig(join(workPath, ".."));
|
|
444
|
+
return findNearestTsconfig(join$1(workPath, ".."));
|
|
218
445
|
};
|
|
219
446
|
|
|
220
447
|
//#endregion
|
|
@@ -290,20 +517,18 @@ const findEntrypoint = async (cwd, options) => {
|
|
|
290
517
|
//#region src/index.ts
|
|
291
518
|
const require = createRequire(import.meta.url);
|
|
292
519
|
const build$1 = async (args) => {
|
|
293
|
-
const entrypoint = args.entrypoint || await findEntrypoint(args.
|
|
520
|
+
const entrypoint = args.entrypoint || await findEntrypoint(args.workPath);
|
|
294
521
|
const tsPromise = typescript({
|
|
295
|
-
...args,
|
|
296
522
|
entrypoint,
|
|
297
|
-
workPath: args.
|
|
523
|
+
workPath: args.workPath
|
|
298
524
|
});
|
|
299
525
|
const rolldownResult = await rolldown({
|
|
300
|
-
...args,
|
|
301
526
|
entrypoint,
|
|
302
|
-
workPath: args.
|
|
303
|
-
repoRootPath: args.
|
|
527
|
+
workPath: args.workPath,
|
|
528
|
+
repoRootPath: args.repoRootPath,
|
|
304
529
|
out: args.out
|
|
305
530
|
});
|
|
306
|
-
await writeFile(join(args.
|
|
531
|
+
await writeFile(join(args.workPath, args.out, ".cervel.json"), JSON.stringify({ handler: rolldownResult.result.handler }, null, 2));
|
|
307
532
|
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Build complete`));
|
|
308
533
|
const typecheckComplete = true;
|
|
309
534
|
const result = tsPromise ? await Promise.race([tsPromise.then(() => typecheckComplete), Promise.resolve(false)]) : true;
|
|
@@ -314,7 +539,7 @@ const build$1 = async (args) => {
|
|
|
314
539
|
};
|
|
315
540
|
};
|
|
316
541
|
const serve = async (args) => {
|
|
317
|
-
const entrypoint = await findEntrypoint(args.
|
|
542
|
+
const entrypoint = await findEntrypoint(args.workPath);
|
|
318
543
|
const srvxBin = join(require.resolve("srvx"), "..", "..", "..", "bin", "srvx.mjs");
|
|
319
544
|
const tsxBin = require.resolve("tsx");
|
|
320
545
|
const restArgs = Object.entries(args.rest).filter(([, value]) => value !== void 0 && value !== false).map(([key, value]) => typeof value === "boolean" ? `--${key}` : `--${key}=${value}`);
|
|
@@ -324,7 +549,7 @@ const serve = async (args) => {
|
|
|
324
549
|
...restArgs,
|
|
325
550
|
entrypoint
|
|
326
551
|
], {
|
|
327
|
-
cwd: args.
|
|
552
|
+
cwd: args.workPath,
|
|
328
553
|
stdio: "inherit"
|
|
329
554
|
});
|
|
330
555
|
};
|
|
@@ -362,15 +587,18 @@ const main = async () => {
|
|
|
362
587
|
const options = parseArgs$1(process.argv.slice(2));
|
|
363
588
|
const { cwd, out,...rest } = options.values;
|
|
364
589
|
const [command, entrypoint] = options.positionals;
|
|
590
|
+
const workPath = cwd;
|
|
591
|
+
const repoRootPath = cwd;
|
|
365
592
|
if (command === "build") {
|
|
366
593
|
const { tsPromise } = await build$1({
|
|
367
|
-
|
|
594
|
+
workPath,
|
|
595
|
+
repoRootPath,
|
|
368
596
|
out,
|
|
369
597
|
entrypoint
|
|
370
598
|
});
|
|
371
599
|
await tsPromise;
|
|
372
600
|
} else await serve({
|
|
373
|
-
|
|
601
|
+
workPath,
|
|
374
602
|
rest
|
|
375
603
|
});
|
|
376
604
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,31 +1,60 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import {
|
|
2
|
+
import { BuildOptions, Files } from "@vercel/build-utils";
|
|
3
|
+
import * as _vercel_build_utils_dist_types_js0 from "@vercel/build-utils/dist/types.js";
|
|
4
|
+
import { ParseArgsConfig } from "node:util";
|
|
3
5
|
|
|
4
6
|
//#region src/find-entrypoint.d.ts
|
|
5
7
|
declare const findEntrypoint: (cwd: string, options?: {
|
|
6
8
|
ignoreRegex?: boolean;
|
|
7
9
|
}) => Promise<string>;
|
|
8
10
|
//#endregion
|
|
11
|
+
//#region src/types.d.ts
|
|
12
|
+
/**
|
|
13
|
+
* Core path options derived from BuildOptions.
|
|
14
|
+
* - workPath: the workspace/project directory (where package.json is)
|
|
15
|
+
* - repoRootPath: the root of the monorepo/repo
|
|
16
|
+
*/
|
|
17
|
+
type PathOptions = Pick<BuildOptions, 'workPath' | 'repoRootPath'>;
|
|
18
|
+
/**
|
|
19
|
+
* Options for the cervel build function.
|
|
20
|
+
*/
|
|
21
|
+
type CervelBuildOptions = PathOptions & {
|
|
22
|
+
entrypoint?: string;
|
|
23
|
+
out: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Options for the cervel serve function.
|
|
27
|
+
*/
|
|
28
|
+
type CervelServeOptions = Pick<BuildOptions, 'workPath'> & {
|
|
29
|
+
rest: Record<string, string | boolean | undefined>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Options for node file tracing.
|
|
33
|
+
*/
|
|
34
|
+
type NodeFileTraceOptions = PathOptions & {
|
|
35
|
+
keepTracedPaths: boolean;
|
|
36
|
+
outDir: string;
|
|
37
|
+
tracedPaths: string[];
|
|
38
|
+
context: {
|
|
39
|
+
files: Files;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/node-file-trace.d.ts
|
|
44
|
+
declare const nodeFileTrace: (args: NodeFileTraceOptions) => Promise<Files>;
|
|
45
|
+
//#endregion
|
|
9
46
|
//#region src/index.d.ts
|
|
10
47
|
type ParseArgsOptionsConfig = NonNullable<ParseArgsConfig['options']>;
|
|
11
48
|
declare const getBuildSummary: (outputDir: string) => Promise<any>;
|
|
12
|
-
declare const build: (args: {
|
|
13
|
-
entrypoint?: string;
|
|
14
|
-
cwd: string;
|
|
15
|
-
out: string;
|
|
16
|
-
}) => Promise<{
|
|
49
|
+
declare const build: (args: CervelBuildOptions) => Promise<{
|
|
17
50
|
rolldownResult: {
|
|
18
|
-
pkg: Record<string, unknown>;
|
|
19
|
-
shouldAddSourcemapSupport: boolean;
|
|
20
51
|
handler: string;
|
|
21
52
|
outputDir: string;
|
|
53
|
+
outputFiles: _vercel_build_utils_dist_types_js0.Files;
|
|
22
54
|
};
|
|
23
55
|
tsPromise: Promise<void> | null | undefined;
|
|
24
56
|
}>;
|
|
25
|
-
declare const serve: (args:
|
|
26
|
-
cwd: string;
|
|
27
|
-
rest: Record<string, string | boolean | undefined>;
|
|
28
|
-
}) => Promise<void>;
|
|
57
|
+
declare const serve: (args: CervelServeOptions) => Promise<void>;
|
|
29
58
|
declare const srvxOptions: ParseArgsOptionsConfig;
|
|
30
59
|
//#endregion
|
|
31
|
-
export { build, findEntrypoint, getBuildSummary, serve, srvxOptions };
|
|
60
|
+
export { type CervelBuildOptions, type CervelServeOptions, type PathOptions, build, findEntrypoint, getBuildSummary, nodeFileTrace, serve, srvxOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,243 @@
|
|
|
1
|
-
import { createRequire } from "module";
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import { readFile, rm
|
|
4
|
-
import { extname, join } from "path";
|
|
1
|
+
import { builtinModules, createRequire } from "node:module";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { lstat, readFile, rm } from "node:fs/promises";
|
|
4
|
+
import { dirname, extname, join, relative } from "node:path";
|
|
5
5
|
import { build as build$1 } from "rolldown";
|
|
6
|
+
import { exports } from "resolve.exports";
|
|
7
|
+
import { isNativeError } from "node:util/types";
|
|
8
|
+
import { FileFsRef, debug, glob } from "@vercel/build-utils";
|
|
9
|
+
import { nodeFileTrace as nodeFileTrace$1, resolve } from "@vercel/nft";
|
|
10
|
+
import { transform } from "oxc-transform";
|
|
11
|
+
import { createRequire as createRequire$1 } from "module";
|
|
6
12
|
import { spawn } from "child_process";
|
|
13
|
+
import { extname as extname$1, join as join$1 } from "path";
|
|
14
|
+
import { existsSync as existsSync$1 } from "fs";
|
|
7
15
|
import execa from "execa";
|
|
16
|
+
import { readFile as readFile$1, writeFile } from "fs/promises";
|
|
8
17
|
|
|
18
|
+
//#region src/node-file-trace.ts
|
|
19
|
+
const nodeFileTrace = async (args) => {
|
|
20
|
+
const files = {};
|
|
21
|
+
const { tracedPaths } = args;
|
|
22
|
+
const compiledSourceFiles = await glob("**/*", {
|
|
23
|
+
cwd: args.outDir,
|
|
24
|
+
follow: true,
|
|
25
|
+
includeDirectories: true
|
|
26
|
+
});
|
|
27
|
+
for (const file of Object.keys(compiledSourceFiles)) files[file] = compiledSourceFiles[file];
|
|
28
|
+
/**
|
|
29
|
+
* While we're not using NFT to process source code, we are using it
|
|
30
|
+
* to tree shake node deps, and include any fs reads for files that are
|
|
31
|
+
* not part of the traced paths or compiled source files.
|
|
32
|
+
* Most of this is identical to the `@vercel/node` implementation
|
|
33
|
+
*/
|
|
34
|
+
const result = await nodeFileTrace$1(Array.from(tracedPaths), {
|
|
35
|
+
base: args.repoRootPath,
|
|
36
|
+
processCwd: args.workPath,
|
|
37
|
+
ts: true,
|
|
38
|
+
mixedModules: true,
|
|
39
|
+
async resolve(id, parent, job, cjsResolve) {
|
|
40
|
+
return resolve(id, parent, job, cjsResolve);
|
|
41
|
+
},
|
|
42
|
+
async readFile(fsPath) {
|
|
43
|
+
try {
|
|
44
|
+
let source = await readFile(fsPath);
|
|
45
|
+
if (fsPath.endsWith(".ts") && !fsPath.endsWith(".d.ts") || fsPath.endsWith(".tsx") || fsPath.endsWith(".mts") || fsPath.endsWith(".cts")) source = (await transform(fsPath, source.toString())).code;
|
|
46
|
+
return source;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (isNativeError(error) && "code" in error && (error.code === "ENOENT" || error.code === "EISDIR")) return null;
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (!args.keepTracedPaths) for (const file of tracedPaths) {
|
|
54
|
+
const relativeFile = relative(args.repoRootPath, file);
|
|
55
|
+
result.fileList.delete(relativeFile);
|
|
56
|
+
}
|
|
57
|
+
debug("NFT traced files count:", result.fileList.size);
|
|
58
|
+
for (const file of result.fileList) {
|
|
59
|
+
const absolutePath = join(args.repoRootPath, file);
|
|
60
|
+
const stats = await lstat(absolutePath);
|
|
61
|
+
const outputPath = file;
|
|
62
|
+
if (stats.isSymbolicLink() || stats.isFile()) files[outputPath] = new FileFsRef({
|
|
63
|
+
fsPath: absolutePath,
|
|
64
|
+
mode: stats.mode
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
debug("Total files in context:", Object.keys(files).length);
|
|
68
|
+
return files;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/plugin.ts
|
|
73
|
+
const CJS_SHIM_PREFIX = "\0cjs-shim:";
|
|
74
|
+
const plugin = (args) => {
|
|
75
|
+
const packageJsonCache = /* @__PURE__ */ new Map();
|
|
76
|
+
const shimMeta = /* @__PURE__ */ new Map();
|
|
77
|
+
const tracedPaths = /* @__PURE__ */ new Set();
|
|
78
|
+
const isBareImport = (id) => {
|
|
79
|
+
return !id.startsWith(".") && !id.startsWith("/") && !/^[a-z][a-z0-9+.-]*:/i.test(id);
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Read and cache package.json contents
|
|
83
|
+
*/
|
|
84
|
+
const getPackageJson = async (pkgPath) => {
|
|
85
|
+
if (packageJsonCache.has(pkgPath)) return packageJsonCache.get(pkgPath);
|
|
86
|
+
try {
|
|
87
|
+
const contents = await readFile(pkgPath, "utf-8");
|
|
88
|
+
const parsed = JSON.parse(contents);
|
|
89
|
+
packageJsonCache.set(pkgPath, parsed);
|
|
90
|
+
return parsed;
|
|
91
|
+
} catch {
|
|
92
|
+
packageJsonCache.set(pkgPath, null);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Determine if a resolved module is CommonJS based on package.json exports
|
|
98
|
+
*/
|
|
99
|
+
const isCommonJS = async (bareImport, resolvedPath, resolvedInfo) => {
|
|
100
|
+
const ext = extname(resolvedPath);
|
|
101
|
+
if (ext === ".cjs") return true;
|
|
102
|
+
if (ext === ".mjs") return false;
|
|
103
|
+
if (ext === ".js" || ext === ".ts") {
|
|
104
|
+
const pkgJsonPath = resolvedInfo.packageJsonPath;
|
|
105
|
+
if (!pkgJsonPath) return true;
|
|
106
|
+
const pkgJson = await getPackageJson(pkgJsonPath);
|
|
107
|
+
if (!pkgJson) return true;
|
|
108
|
+
const pkgDir = dirname(pkgJsonPath);
|
|
109
|
+
const relativePath = resolvedPath.startsWith(pkgDir) ? resolvedPath.slice(pkgDir.length + 1).replace(/\\/g, "/") : null;
|
|
110
|
+
if (!relativePath) return pkgJson.type !== "module";
|
|
111
|
+
const pkgName = pkgJson.name || "";
|
|
112
|
+
const subpath = bareImport.startsWith(pkgName) ? `.${bareImport.slice(pkgName.length)}` || "." : ".";
|
|
113
|
+
try {
|
|
114
|
+
if (exports(pkgJson, subpath, {
|
|
115
|
+
require: false,
|
|
116
|
+
conditions: ["node", "import"]
|
|
117
|
+
})?.some((p) => p === relativePath || p === `./${relativePath}`)) return false;
|
|
118
|
+
if (exports(pkgJson, subpath, {
|
|
119
|
+
require: true,
|
|
120
|
+
conditions: ["node", "require"]
|
|
121
|
+
})?.some((p) => p === relativePath || p === `./${relativePath}`)) return true;
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.warn("Export resolution failed::", err);
|
|
124
|
+
}
|
|
125
|
+
if (pkgJson.module) return false;
|
|
126
|
+
return pkgJson.type !== "module";
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
};
|
|
130
|
+
const isLocalImport = (id) => {
|
|
131
|
+
if (id.startsWith("node:")) return false;
|
|
132
|
+
if (id.includes("node_modules")) return false;
|
|
133
|
+
return true;
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
name: "cervel",
|
|
137
|
+
resolveId: {
|
|
138
|
+
order: "pre",
|
|
139
|
+
async handler(id, importer, rOpts) {
|
|
140
|
+
if (id.startsWith(CJS_SHIM_PREFIX)) return {
|
|
141
|
+
id,
|
|
142
|
+
external: false
|
|
143
|
+
};
|
|
144
|
+
const resolved = await this.resolve(id, importer, rOpts);
|
|
145
|
+
if (builtinModules.includes(id)) return {
|
|
146
|
+
id: `node:${id}`,
|
|
147
|
+
external: true
|
|
148
|
+
};
|
|
149
|
+
if (resolved?.id && isLocalImport(resolved.id)) tracedPaths.add(resolved.id);
|
|
150
|
+
if (importer?.startsWith(CJS_SHIM_PREFIX) && isBareImport(id)) return {
|
|
151
|
+
id,
|
|
152
|
+
external: true
|
|
153
|
+
};
|
|
154
|
+
if (importer && isBareImport(id) && resolved?.id?.includes("node_modules")) {
|
|
155
|
+
if (args.shimBareImports) {
|
|
156
|
+
if (await isCommonJS(id, resolved.id, resolved)) {
|
|
157
|
+
const importerPkgJsonPath = (await this.resolve(importer))?.packageJsonPath;
|
|
158
|
+
if (importerPkgJsonPath) {
|
|
159
|
+
const importerPkgDir = relative(args.repoRootPath, dirname(importerPkgJsonPath));
|
|
160
|
+
const shimId$1 = `${CJS_SHIM_PREFIX}${importerPkgDir.replace(/\//g, "_")}_${id.replace(/\//g, "_")}`;
|
|
161
|
+
shimMeta.set(shimId$1, {
|
|
162
|
+
pkgDir: importerPkgDir,
|
|
163
|
+
pkgName: id
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
id: shimId$1,
|
|
167
|
+
external: false
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const shimId = `${CJS_SHIM_PREFIX}${id.replace(/\//g, "_")}`;
|
|
171
|
+
shimMeta.set(shimId, {
|
|
172
|
+
pkgDir: "",
|
|
173
|
+
pkgName: id
|
|
174
|
+
});
|
|
175
|
+
return {
|
|
176
|
+
id: shimId,
|
|
177
|
+
external: false
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
external: true,
|
|
183
|
+
id
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (importer && isBareImport(id)) return resolved;
|
|
187
|
+
return {
|
|
188
|
+
external: true,
|
|
189
|
+
...resolved,
|
|
190
|
+
id: resolved?.id || id
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
load: { async handler(id) {
|
|
195
|
+
if (id.startsWith(CJS_SHIM_PREFIX)) {
|
|
196
|
+
const meta = shimMeta.get(id);
|
|
197
|
+
if (!meta) return { code: `module.exports = require('${id.slice(10)}');` };
|
|
198
|
+
const { pkgDir, pkgName } = meta;
|
|
199
|
+
if (pkgDir) return { code: `
|
|
200
|
+
import { createRequire } from 'node:module';
|
|
201
|
+
import { fileURLToPath } from 'node:url';
|
|
202
|
+
import { dirname, join } from 'node:path';
|
|
203
|
+
|
|
204
|
+
const requireFromContext = createRequire(join(dirname(fileURLToPath(import.meta.url)), '${join("..", pkgDir, "package.json")}'));
|
|
205
|
+
module.exports = requireFromContext('${pkgName}');
|
|
206
|
+
`.trim() };
|
|
207
|
+
return { code: `module.exports = require('${pkgName}');` };
|
|
208
|
+
}
|
|
209
|
+
return null;
|
|
210
|
+
} },
|
|
211
|
+
writeBundle: {
|
|
212
|
+
order: "post",
|
|
213
|
+
async handler() {
|
|
214
|
+
const files = await nodeFileTrace({
|
|
215
|
+
outDir: args.outDir,
|
|
216
|
+
tracedPaths: Array.from(tracedPaths),
|
|
217
|
+
repoRootPath: args.repoRootPath,
|
|
218
|
+
workPath: args.workPath,
|
|
219
|
+
context: args.context,
|
|
220
|
+
keepTracedPaths: false
|
|
221
|
+
});
|
|
222
|
+
args.context.files = files;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
//#endregion
|
|
9
229
|
//#region src/rolldown.ts
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
230
|
+
const __dirname__filenameShim = `
|
|
231
|
+
import { createRequire as __createRequire } from 'node:module';
|
|
232
|
+
import { fileURLToPath as __fileURLToPath } from 'node:url';
|
|
233
|
+
import { dirname as __dirname_ } from 'node:path';
|
|
234
|
+
const require = __createRequire(import.meta.url);
|
|
235
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
236
|
+
const __dirname = __dirname_(__filename);
|
|
237
|
+
`.trim();
|
|
16
238
|
const rolldown = async (args) => {
|
|
17
|
-
const baseDir = args.repoRootPath || args.workPath;
|
|
18
239
|
const entrypointPath = join(args.workPath, args.entrypoint);
|
|
19
|
-
const
|
|
240
|
+
const outputDir = join(args.workPath, args.out);
|
|
20
241
|
const extension = extname(args.entrypoint);
|
|
21
242
|
const extensionMap = {
|
|
22
243
|
".ts": {
|
|
@@ -46,7 +267,6 @@ const rolldown = async (args) => {
|
|
|
46
267
|
};
|
|
47
268
|
const extensionInfo = extensionMap[extension] || extensionMap[".js"];
|
|
48
269
|
let resolvedFormat = extensionInfo.format === "auto" ? void 0 : extensionInfo.format;
|
|
49
|
-
const resolvedExtension = extensionInfo.extension;
|
|
50
270
|
const packageJsonPath = join(args.workPath, "package.json");
|
|
51
271
|
const external = [];
|
|
52
272
|
let pkg = {};
|
|
@@ -64,21 +284,29 @@ const rolldown = async (args) => {
|
|
|
64
284
|
for (const dependency of Object.keys(pkg.peerDependencies || {})) external.push(dependency);
|
|
65
285
|
for (const dependency of Object.keys(pkg.optionalDependencies || {})) external.push(dependency);
|
|
66
286
|
}
|
|
67
|
-
const
|
|
68
|
-
const
|
|
287
|
+
const resolvedExtension = resolvedFormat === "esm" ? "mjs" : "cjs";
|
|
288
|
+
const context = { files: {} };
|
|
69
289
|
const out = await build$1({
|
|
70
290
|
input: entrypointPath,
|
|
71
|
-
cwd:
|
|
291
|
+
cwd: args.workPath,
|
|
72
292
|
platform: "node",
|
|
73
293
|
tsconfig: true,
|
|
74
|
-
|
|
294
|
+
plugins: [plugin({
|
|
295
|
+
repoRootPath: args.repoRootPath,
|
|
296
|
+
outDir: outputDir,
|
|
297
|
+
workPath: args.workPath,
|
|
298
|
+
shimBareImports: resolvedFormat === "esm",
|
|
299
|
+
context
|
|
300
|
+
})],
|
|
75
301
|
output: {
|
|
76
302
|
cleanDir: true,
|
|
77
303
|
dir: outputDir,
|
|
78
304
|
format: resolvedFormat,
|
|
79
305
|
entryFileNames: `[name].${resolvedExtension}`,
|
|
80
306
|
preserveModules: true,
|
|
81
|
-
|
|
307
|
+
preserveModulesRoot: args.repoRootPath,
|
|
308
|
+
sourcemap: false,
|
|
309
|
+
banner: resolvedFormat === "esm" ? __dirname__filenameShim : void 0
|
|
82
310
|
}
|
|
83
311
|
});
|
|
84
312
|
let handler = null;
|
|
@@ -94,10 +322,9 @@ const rolldown = async (args) => {
|
|
|
94
322
|
};
|
|
95
323
|
return {
|
|
96
324
|
result: {
|
|
97
|
-
pkg,
|
|
98
|
-
shouldAddSourcemapSupport,
|
|
99
325
|
handler,
|
|
100
|
-
outputDir
|
|
326
|
+
outputDir,
|
|
327
|
+
outputFiles: context.files
|
|
101
328
|
},
|
|
102
329
|
cleanup
|
|
103
330
|
};
|
|
@@ -134,9 +361,9 @@ const Colors = {
|
|
|
134
361
|
|
|
135
362
|
//#endregion
|
|
136
363
|
//#region src/typescript.ts
|
|
137
|
-
const require_ = createRequire(import.meta.url);
|
|
364
|
+
const require_ = createRequire$1(import.meta.url);
|
|
138
365
|
const typescript = (args) => {
|
|
139
|
-
const extension = extname(args.entrypoint);
|
|
366
|
+
const extension = extname$1(args.entrypoint);
|
|
140
367
|
if (![
|
|
141
368
|
".ts",
|
|
142
369
|
".mts",
|
|
@@ -183,11 +410,11 @@ async function doTypeCheck(args, tscPath) {
|
|
|
183
410
|
child.stderr?.on("data", (data) => {
|
|
184
411
|
stderr += data.toString();
|
|
185
412
|
});
|
|
186
|
-
await new Promise((resolve, reject) => {
|
|
413
|
+
await new Promise((resolve$1, reject) => {
|
|
187
414
|
child.on("close", (code) => {
|
|
188
415
|
if (code === 0) {
|
|
189
416
|
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck complete`));
|
|
190
|
-
resolve();
|
|
417
|
+
resolve$1();
|
|
191
418
|
} else {
|
|
192
419
|
const output = stdout || stderr;
|
|
193
420
|
if (output) {
|
|
@@ -210,10 +437,10 @@ const resolveTscPath = (args) => {
|
|
|
210
437
|
}
|
|
211
438
|
};
|
|
212
439
|
const findNearestTsconfig = async (workPath) => {
|
|
213
|
-
const tsconfigPath = join(workPath, "tsconfig.json");
|
|
214
|
-
if (existsSync(tsconfigPath)) return tsconfigPath;
|
|
440
|
+
const tsconfigPath = join$1(workPath, "tsconfig.json");
|
|
441
|
+
if (existsSync$1(tsconfigPath)) return tsconfigPath;
|
|
215
442
|
if (workPath === "/") return;
|
|
216
|
-
return findNearestTsconfig(join(workPath, ".."));
|
|
443
|
+
return findNearestTsconfig(join$1(workPath, ".."));
|
|
217
444
|
};
|
|
218
445
|
|
|
219
446
|
//#endregion
|
|
@@ -289,24 +516,22 @@ const findEntrypoint = async (cwd, options) => {
|
|
|
289
516
|
//#region src/index.ts
|
|
290
517
|
const require = createRequire(import.meta.url);
|
|
291
518
|
const getBuildSummary = async (outputDir) => {
|
|
292
|
-
const buildSummary = await readFile(join(outputDir, ".cervel.json"), "utf-8");
|
|
519
|
+
const buildSummary = await readFile$1(join(outputDir, ".cervel.json"), "utf-8");
|
|
293
520
|
return JSON.parse(buildSummary);
|
|
294
521
|
};
|
|
295
522
|
const build = async (args) => {
|
|
296
|
-
const entrypoint = args.entrypoint || await findEntrypoint(args.
|
|
523
|
+
const entrypoint = args.entrypoint || await findEntrypoint(args.workPath);
|
|
297
524
|
const tsPromise = typescript({
|
|
298
|
-
...args,
|
|
299
525
|
entrypoint,
|
|
300
|
-
workPath: args.
|
|
526
|
+
workPath: args.workPath
|
|
301
527
|
});
|
|
302
528
|
const rolldownResult = await rolldown({
|
|
303
|
-
...args,
|
|
304
529
|
entrypoint,
|
|
305
|
-
workPath: args.
|
|
306
|
-
repoRootPath: args.
|
|
530
|
+
workPath: args.workPath,
|
|
531
|
+
repoRootPath: args.repoRootPath,
|
|
307
532
|
out: args.out
|
|
308
533
|
});
|
|
309
|
-
await writeFile(join(args.
|
|
534
|
+
await writeFile(join(args.workPath, args.out, ".cervel.json"), JSON.stringify({ handler: rolldownResult.result.handler }, null, 2));
|
|
310
535
|
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Build complete`));
|
|
311
536
|
const typecheckComplete = true;
|
|
312
537
|
const result = tsPromise ? await Promise.race([tsPromise.then(() => typecheckComplete), Promise.resolve(false)]) : true;
|
|
@@ -317,7 +542,7 @@ const build = async (args) => {
|
|
|
317
542
|
};
|
|
318
543
|
};
|
|
319
544
|
const serve = async (args) => {
|
|
320
|
-
const entrypoint = await findEntrypoint(args.
|
|
545
|
+
const entrypoint = await findEntrypoint(args.workPath);
|
|
321
546
|
const srvxBin = join(require.resolve("srvx"), "..", "..", "..", "bin", "srvx.mjs");
|
|
322
547
|
const tsxBin = require.resolve("tsx");
|
|
323
548
|
const restArgs = Object.entries(args.rest).filter(([, value]) => value !== void 0 && value !== false).map(([key, value]) => typeof value === "boolean" ? `--${key}` : `--${key}=${value}`);
|
|
@@ -327,7 +552,7 @@ const serve = async (args) => {
|
|
|
327
552
|
...restArgs,
|
|
328
553
|
entrypoint
|
|
329
554
|
], {
|
|
330
|
-
cwd: args.
|
|
555
|
+
cwd: args.workPath,
|
|
331
556
|
stdio: "inherit"
|
|
332
557
|
});
|
|
333
558
|
};
|
|
@@ -360,4 +585,4 @@ const srvxOptions = {
|
|
|
360
585
|
};
|
|
361
586
|
|
|
362
587
|
//#endregion
|
|
363
|
-
export { build, findEntrypoint, getBuildSummary, serve, srvxOptions };
|
|
588
|
+
export { build, findEntrypoint, getBuildSummary, nodeFileTrace, serve, srvxOptions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/cervel",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://vercel.com/docs",
|
|
6
6
|
"publishConfig": {
|
|
@@ -28,10 +28,15 @@
|
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"@vercel/nft": "1.3.0",
|
|
31
32
|
"execa": "3.2.0",
|
|
32
|
-
"
|
|
33
|
+
"nf3": "0.3.6",
|
|
34
|
+
"oxc-transform": "0.111.0",
|
|
35
|
+
"resolve.exports": "2.0.3",
|
|
36
|
+
"rolldown": "1.0.0-rc.1",
|
|
33
37
|
"srvx": "0.8.9",
|
|
34
|
-
"tsx": "4.21.0"
|
|
38
|
+
"tsx": "4.21.0",
|
|
39
|
+
"@vercel/build-utils": "13.2.16"
|
|
35
40
|
},
|
|
36
41
|
"peerDependencies": {
|
|
37
42
|
"typescript": "^4.0.0 || ^5.0.0"
|