@vercel/backends 0.0.27 → 0.0.28
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/index.d.mts +4 -5
- package/dist/index.mjs +889 -412
- package/dist/introspection/express.mjs +1 -2
- package/dist/introspection/hono.mjs +2 -5
- package/dist/introspection/loaders/cjs.cjs +2 -6
- package/dist/rolldown/cjs-hooks.cjs +208 -0
- package/dist/rolldown/cjs-hooks.d.cts +1 -0
- package/dist/rolldown/esm.d.mts +1 -0
- package/dist/rolldown/esm.mjs +7 -0
- package/dist/rolldown/hooks.d.mts +27 -0
- package/dist/rolldown/hooks.mjs +84 -0
- package/dist/rolldown/index.d.mts +16 -0
- package/dist/rolldown/index.mjs +301 -0
- package/package.json +5 -7
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { builtinModules } from "node:module";
|
|
2
|
+
import { FileBlob, FileFsRef, Span, isBackendFramework } from "@vercel/build-utils";
|
|
3
|
+
import { dirname, extname, join, relative } from "node:path";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
6
|
+
import { build } from "rolldown";
|
|
7
|
+
import { nodeFileTrace } from "@vercel/nft";
|
|
8
|
+
import { isNativeError } from "node:util/types";
|
|
9
|
+
import { transform } from "oxc-transform";
|
|
10
|
+
import { exports } from "resolve.exports";
|
|
11
|
+
|
|
12
|
+
//#region src/rolldown/resolve-format.ts
|
|
13
|
+
const resolveEntrypointAndFormat = async (args) => {
|
|
14
|
+
const extension = extname(args.entrypoint);
|
|
15
|
+
const extensionMap = {
|
|
16
|
+
".ts": {
|
|
17
|
+
format: "auto",
|
|
18
|
+
extension: "js"
|
|
19
|
+
},
|
|
20
|
+
".mts": {
|
|
21
|
+
format: "esm",
|
|
22
|
+
extension: "mjs"
|
|
23
|
+
},
|
|
24
|
+
".cts": {
|
|
25
|
+
format: "cjs",
|
|
26
|
+
extension: "cjs"
|
|
27
|
+
},
|
|
28
|
+
".cjs": {
|
|
29
|
+
format: "cjs",
|
|
30
|
+
extension: "cjs"
|
|
31
|
+
},
|
|
32
|
+
".js": {
|
|
33
|
+
format: "auto",
|
|
34
|
+
extension: "js"
|
|
35
|
+
},
|
|
36
|
+
".mjs": {
|
|
37
|
+
format: "esm",
|
|
38
|
+
extension: "mjs"
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const extensionInfo = extensionMap[extension] || extensionMap[".js"];
|
|
42
|
+
let resolvedFormat = extensionInfo.format === "auto" ? void 0 : extensionInfo.format;
|
|
43
|
+
const packageJsonPath = join(args.workPath, "package.json");
|
|
44
|
+
let pkg = {};
|
|
45
|
+
if (existsSync(packageJsonPath)) {
|
|
46
|
+
const source = await readFile(packageJsonPath, "utf8");
|
|
47
|
+
try {
|
|
48
|
+
pkg = JSON.parse(source.toString());
|
|
49
|
+
} catch (_e) {
|
|
50
|
+
pkg = {};
|
|
51
|
+
}
|
|
52
|
+
if (extensionInfo.format === "auto") if (pkg.type === "module") resolvedFormat = "esm";
|
|
53
|
+
else resolvedFormat = "cjs";
|
|
54
|
+
}
|
|
55
|
+
if (!resolvedFormat) throw new Error(`Unable to resolve format for ${args.entrypoint}`);
|
|
56
|
+
return {
|
|
57
|
+
format: resolvedFormat,
|
|
58
|
+
extension: resolvedFormat === "esm" ? "mjs" : "cjs"
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/rolldown/nft.ts
|
|
64
|
+
const nft = async (args) => {
|
|
65
|
+
const nftSpan = args.span.child("vc.builder.backends.nft");
|
|
66
|
+
const runNft = async () => {
|
|
67
|
+
const nftResult = await nodeFileTrace(Array.from(args.localBuildFiles), {
|
|
68
|
+
base: args.repoRootPath,
|
|
69
|
+
processCwd: args.workPath,
|
|
70
|
+
ts: true,
|
|
71
|
+
mixedModules: true,
|
|
72
|
+
ignore: args.ignoreNodeModules ? (path) => path.includes("node_modules") : void 0,
|
|
73
|
+
async readFile(fsPath) {
|
|
74
|
+
try {
|
|
75
|
+
let source = await readFile(fsPath);
|
|
76
|
+
if (isTypeScriptFile(fsPath)) source = (await transform(fsPath, source.toString())).code;
|
|
77
|
+
return source;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (isNativeError(error) && "code" in error && (error.code === "ENOENT" || error.code === "EISDIR")) return null;
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
for (const file of nftResult.fileList) {
|
|
85
|
+
const absolutePath = join(args.repoRootPath, file);
|
|
86
|
+
const stats = await lstat(absolutePath);
|
|
87
|
+
const outputPath = file;
|
|
88
|
+
if (args.localBuildFiles.has(join(args.repoRootPath, outputPath))) continue;
|
|
89
|
+
if (stats.isSymbolicLink() || stats.isFile()) if (args.ignoreNodeModules) {
|
|
90
|
+
const content = await readFile(absolutePath, "utf-8");
|
|
91
|
+
args.files[outputPath] = new FileBlob({
|
|
92
|
+
data: content,
|
|
93
|
+
mode: stats.mode
|
|
94
|
+
});
|
|
95
|
+
} else args.files[outputPath] = new FileFsRef({
|
|
96
|
+
fsPath: absolutePath,
|
|
97
|
+
mode: stats.mode
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
await nftSpan.trace(runNft);
|
|
102
|
+
};
|
|
103
|
+
const isTypeScriptFile = (fsPath) => {
|
|
104
|
+
return fsPath.endsWith(".ts") || fsPath.endsWith(".tsx") || fsPath.endsWith(".mts") || fsPath.endsWith(".cts");
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/rolldown/index.ts
|
|
109
|
+
const PLUGIN_NAME = "vercel:backends";
|
|
110
|
+
const CJS_SHIM_PREFIX = "\0cjs-shim:";
|
|
111
|
+
const rolldown = async (args) => {
|
|
112
|
+
const files = {};
|
|
113
|
+
const { format, extension } = await resolveEntrypointAndFormat(args);
|
|
114
|
+
const localBuildFiles = /* @__PURE__ */ new Set();
|
|
115
|
+
let handler = null;
|
|
116
|
+
const packageJsonCache = /* @__PURE__ */ new Map();
|
|
117
|
+
const shimMeta = /* @__PURE__ */ new Map();
|
|
118
|
+
const framework = {
|
|
119
|
+
slug: "",
|
|
120
|
+
version: ""
|
|
121
|
+
};
|
|
122
|
+
const getPackageJson = async (pkgPath) => {
|
|
123
|
+
if (packageJsonCache.has(pkgPath)) return packageJsonCache.get(pkgPath);
|
|
124
|
+
try {
|
|
125
|
+
const contents = await readFile(pkgPath, "utf-8");
|
|
126
|
+
const parsed = JSON.parse(contents);
|
|
127
|
+
packageJsonCache.set(pkgPath, parsed);
|
|
128
|
+
return parsed;
|
|
129
|
+
} catch {
|
|
130
|
+
packageJsonCache.set(pkgPath, null);
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const isCommonJS = async (bareImport, resolvedPath, resolvedInfo) => {
|
|
135
|
+
const ext = extname(resolvedPath);
|
|
136
|
+
if (ext === ".cjs") return true;
|
|
137
|
+
if (ext === ".mjs") return false;
|
|
138
|
+
if (ext === ".js" || ext === ".ts") {
|
|
139
|
+
const pkgJsonPath = resolvedInfo.packageJsonPath;
|
|
140
|
+
if (!pkgJsonPath) return true;
|
|
141
|
+
const pkgJson = await getPackageJson(pkgJsonPath);
|
|
142
|
+
if (!pkgJson) return true;
|
|
143
|
+
const pkgDir = dirname(pkgJsonPath);
|
|
144
|
+
const relativePath = resolvedPath.slice(pkgDir.length + 1).replace(/\\/g, "/");
|
|
145
|
+
const pkgName = pkgJson.name || "";
|
|
146
|
+
const subpath = bareImport.startsWith(pkgName) ? `.${bareImport.slice(pkgName.length)}` || "." : ".";
|
|
147
|
+
try {
|
|
148
|
+
if (exports(pkgJson, subpath, {
|
|
149
|
+
require: false,
|
|
150
|
+
conditions: ["node", "import"]
|
|
151
|
+
})?.some((p) => p === relativePath || p === `./${relativePath}`)) return false;
|
|
152
|
+
if (exports(pkgJson, subpath, {
|
|
153
|
+
require: true,
|
|
154
|
+
conditions: ["node", "require"]
|
|
155
|
+
})?.some((p) => p === relativePath || p === `./${relativePath}`)) return true;
|
|
156
|
+
} catch {}
|
|
157
|
+
if (pkgJson.module) return false;
|
|
158
|
+
return pkgJson.type !== "module";
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
161
|
+
};
|
|
162
|
+
const isBareImport = (id) => {
|
|
163
|
+
return !id.startsWith(".") && !id.startsWith("/") && !/^[a-z][a-z0-9+.-]*:/i.test(id);
|
|
164
|
+
};
|
|
165
|
+
const isNodeModule = (resolved) => {
|
|
166
|
+
return resolved?.id?.includes("node_modules") ?? false;
|
|
167
|
+
};
|
|
168
|
+
const isNodeBuiltin = (id) => {
|
|
169
|
+
const normalizedId = id.includes(":") ? id.split(":")[1] : id;
|
|
170
|
+
return builtinModules.includes(normalizedId);
|
|
171
|
+
};
|
|
172
|
+
const isLocalImport = (id) => {
|
|
173
|
+
return !id.startsWith("node:") && !id.includes("node_modules");
|
|
174
|
+
};
|
|
175
|
+
const plugin = () => {
|
|
176
|
+
return {
|
|
177
|
+
name: PLUGIN_NAME,
|
|
178
|
+
resolveId: {
|
|
179
|
+
order: "pre",
|
|
180
|
+
async handler(id, importer, rOpts) {
|
|
181
|
+
if (id.startsWith(CJS_SHIM_PREFIX)) return {
|
|
182
|
+
id,
|
|
183
|
+
external: false
|
|
184
|
+
};
|
|
185
|
+
const resolved = await this.resolve(id, importer, rOpts);
|
|
186
|
+
if (isNodeBuiltin(id)) return {
|
|
187
|
+
id: id.startsWith("node:") ? id : `node:${id}`,
|
|
188
|
+
external: true
|
|
189
|
+
};
|
|
190
|
+
if (resolved?.id && isLocalImport(resolved.id)) localBuildFiles.add(resolved.id);
|
|
191
|
+
else if (!resolved) localBuildFiles.add(join(args.workPath, id));
|
|
192
|
+
if (importer?.startsWith(CJS_SHIM_PREFIX) && isBareImport(id)) return {
|
|
193
|
+
id,
|
|
194
|
+
external: true
|
|
195
|
+
};
|
|
196
|
+
if (importer && isBareImport(id) && isNodeModule(resolved)) {
|
|
197
|
+
if (isBackendFramework(id) && resolved?.packageJsonPath) try {
|
|
198
|
+
const pkg = await readFile(resolved.packageJsonPath, "utf8");
|
|
199
|
+
const pkgJson = JSON.parse(pkg);
|
|
200
|
+
framework.slug = pkgJson.name;
|
|
201
|
+
framework.version = pkgJson.version;
|
|
202
|
+
} catch {}
|
|
203
|
+
if (resolved ? await isCommonJS(id, resolved.id, resolved) : false) {
|
|
204
|
+
const importerPkgJsonPath = (await this.resolve(importer))?.packageJsonPath;
|
|
205
|
+
if (importerPkgJsonPath) {
|
|
206
|
+
const importerPkgDir = relative(args.repoRootPath, dirname(importerPkgJsonPath));
|
|
207
|
+
const shimId$1 = `${CJS_SHIM_PREFIX}${importerPkgDir.replace(/\//g, "_")}_${id.replace(/\//g, "_")}`;
|
|
208
|
+
shimMeta.set(shimId$1, {
|
|
209
|
+
pkgDir: importerPkgDir,
|
|
210
|
+
pkgName: id
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
id: shimId$1,
|
|
214
|
+
external: false
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const shimId = `${CJS_SHIM_PREFIX}${id.replace(/\//g, "_")}`;
|
|
218
|
+
shimMeta.set(shimId, {
|
|
219
|
+
pkgDir: "",
|
|
220
|
+
pkgName: id
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
id: shimId,
|
|
224
|
+
external: false
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
id,
|
|
229
|
+
external: true
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
if (importer && isBareImport(id)) return resolved;
|
|
233
|
+
if (resolved && !isNodeModule(resolved)) return resolved;
|
|
234
|
+
return resolved;
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
load: { async handler(id) {
|
|
238
|
+
if (id.startsWith(CJS_SHIM_PREFIX)) {
|
|
239
|
+
const meta = shimMeta.get(id);
|
|
240
|
+
if (!meta) return { code: `module.exports = require('${id.slice(10)}');` };
|
|
241
|
+
const { pkgDir, pkgName } = meta;
|
|
242
|
+
return { code: `
|
|
243
|
+
import { createRequire } from 'node:module';
|
|
244
|
+
import { fileURLToPath } from 'node:url';
|
|
245
|
+
import { dirname, join } from 'node:path';
|
|
246
|
+
|
|
247
|
+
const requireFromContext = createRequire(join(dirname(fileURLToPath(import.meta.url)), '${pkgDir ? join("..", pkgDir, "package.json") : "../package.json"}'));
|
|
248
|
+
module.exports = requireFromContext('${pkgName}');
|
|
249
|
+
`.trim() };
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
} }
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
const runRolldown = () => build({
|
|
256
|
+
input: args.entrypoint,
|
|
257
|
+
write: false,
|
|
258
|
+
cwd: args.workPath,
|
|
259
|
+
platform: "node",
|
|
260
|
+
transform: { define: format === "esm" ? {
|
|
261
|
+
__dirname: "import.meta.dirname",
|
|
262
|
+
__filename: "import.meta.filename"
|
|
263
|
+
} : void 0 },
|
|
264
|
+
tsconfig: true,
|
|
265
|
+
plugins: [plugin()],
|
|
266
|
+
output: {
|
|
267
|
+
cleanDir: true,
|
|
268
|
+
format,
|
|
269
|
+
entryFileNames: `[name].${extension}`,
|
|
270
|
+
preserveModules: true,
|
|
271
|
+
preserveModulesRoot: args.repoRootPath,
|
|
272
|
+
sourcemap: false
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
const rolldownSpan = args.span?.child("vc.builder.backends.rolldown");
|
|
276
|
+
const out = await rolldownSpan?.trace(runRolldown) || await runRolldown();
|
|
277
|
+
for (const file of out.output) if (file.type === "chunk") {
|
|
278
|
+
if (file.isEntry) handler = file.fileName;
|
|
279
|
+
files[file.fileName] = new FileBlob({
|
|
280
|
+
data: file.code,
|
|
281
|
+
mode: 420
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
await nft({
|
|
285
|
+
...args,
|
|
286
|
+
localBuildFiles,
|
|
287
|
+
files,
|
|
288
|
+
span: rolldownSpan ?? new Span({ name: "vc.builder.backends.nft" }),
|
|
289
|
+
ignoreNodeModules: true
|
|
290
|
+
});
|
|
291
|
+
if (!handler) throw new Error(`Unable to resolve build handler for entrypoint: ${args.entrypoint}`);
|
|
292
|
+
return {
|
|
293
|
+
files,
|
|
294
|
+
handler,
|
|
295
|
+
framework,
|
|
296
|
+
localBuildFiles
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
//#endregion
|
|
301
|
+
export { rolldown };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/backends",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"homepage": "https://vercel.com/docs",
|
|
@@ -11,11 +11,9 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": "./dist/index.mjs",
|
|
13
13
|
"./package.json": "./package.json",
|
|
14
|
-
"./
|
|
15
|
-
"./
|
|
16
|
-
"./
|
|
17
|
-
"./introspection/loaders/rolldown-esm": "./dist/introspection/loaders/rolldown-esm.mjs",
|
|
18
|
-
"./introspection/loaders/rolldown-hooks": "./dist/introspection/loaders/rolldown-hooks.mjs"
|
|
14
|
+
"./rolldown/esm": "./dist/rolldown/esm.mjs",
|
|
15
|
+
"./rolldown/hooks": "./dist/rolldown/hooks.mjs",
|
|
16
|
+
"./rolldown/cjs-hooks": "./dist/rolldown/cjs-hooks.cjs"
|
|
19
17
|
},
|
|
20
18
|
"repository": {
|
|
21
19
|
"type": "git",
|
|
@@ -36,7 +34,7 @@
|
|
|
36
34
|
"srvx": "0.8.9",
|
|
37
35
|
"tsx": "4.21.0",
|
|
38
36
|
"zod": "3.22.4",
|
|
39
|
-
"@vercel/build-utils": "13.3.
|
|
37
|
+
"@vercel/build-utils": "13.3.1"
|
|
40
38
|
},
|
|
41
39
|
"peerDependencies": {
|
|
42
40
|
"typescript": "^4.0.0 || ^5.0.0"
|