@vercel/fs-detectors 5.8.15 → 5.8.16
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/services/resolve.js +61 -23
- package/dist/services/utils.d.ts +12 -0
- package/dist/services/utils.js +29 -7
- package/package.json +3 -3
package/dist/services/resolve.js
CHANGED
|
@@ -126,12 +126,14 @@ async function inferWorkspaceFromNearestManifest({
|
|
|
126
126
|
async function detectFrameworkFromWorkspace({
|
|
127
127
|
fs,
|
|
128
128
|
workspace,
|
|
129
|
-
serviceName
|
|
129
|
+
serviceName,
|
|
130
|
+
runtime
|
|
130
131
|
}) {
|
|
131
132
|
const serviceFs = workspace === "." ? fs : fs.chdir(workspace);
|
|
133
|
+
const frameworkCandidates = (0, import_utils.filterFrameworksByRuntime)(import_frameworks.default, runtime);
|
|
132
134
|
const frameworks = await (0, import_detect_framework.detectFrameworks)({
|
|
133
135
|
fs: serviceFs,
|
|
134
|
-
frameworkList:
|
|
136
|
+
frameworkList: frameworkCandidates
|
|
135
137
|
});
|
|
136
138
|
if (frameworks.length > 1) {
|
|
137
139
|
const frameworkNames = frameworks.map((f) => f.name).join(", ");
|
|
@@ -212,6 +214,16 @@ function validateServiceConfig(name, config) {
|
|
|
212
214
|
serviceName: name
|
|
213
215
|
};
|
|
214
216
|
}
|
|
217
|
+
if (config.runtime && config.framework) {
|
|
218
|
+
const frameworkRuntime = (0, import_utils.inferRuntimeFromFramework)(config.framework);
|
|
219
|
+
if (frameworkRuntime && frameworkRuntime !== config.runtime) {
|
|
220
|
+
return {
|
|
221
|
+
code: "RUNTIME_FRAMEWORK_MISMATCH",
|
|
222
|
+
message: `Service "${name}" has conflicting runtime/framework: runtime "${config.runtime}" is incompatible with framework "${config.framework}" (runtime "${frameworkRuntime}").`,
|
|
223
|
+
serviceName: name
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
215
227
|
const hasFramework = Boolean(config.framework);
|
|
216
228
|
const hasBuilderOrRuntime = Boolean(config.builder || config.runtime);
|
|
217
229
|
const hasEntrypoint = Boolean(config.entrypoint);
|
|
@@ -395,30 +407,56 @@ async function resolveAllConfiguredServices(services, fs, routePrefixSource = "c
|
|
|
395
407
|
}
|
|
396
408
|
}
|
|
397
409
|
let resolvedConfig = serviceConfig;
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
serviceName: name
|
|
405
|
-
});
|
|
406
|
-
if (error) {
|
|
407
|
-
errors.push(error);
|
|
408
|
-
continue;
|
|
409
|
-
}
|
|
410
|
-
if (!framework) {
|
|
411
|
-
errors.push({
|
|
412
|
-
code: "MISSING_SERVICE_FRAMEWORK",
|
|
413
|
-
message: `Service "${name}" uses directory entrypoint "${serviceConfig.entrypoint}" but no framework could be detected in "${workspace}". Specify "framework" explicitly or use a file entrypoint.`,
|
|
410
|
+
if (!serviceConfig.framework && resolvedEntrypoint) {
|
|
411
|
+
if (resolvedEntrypoint.isDirectory) {
|
|
412
|
+
const workspace = resolvedEntrypoint.normalized;
|
|
413
|
+
const { framework, error } = await detectFrameworkFromWorkspace({
|
|
414
|
+
fs,
|
|
415
|
+
workspace,
|
|
414
416
|
serviceName: name
|
|
415
417
|
});
|
|
416
|
-
|
|
418
|
+
if (error) {
|
|
419
|
+
errors.push(error);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (!framework) {
|
|
423
|
+
errors.push({
|
|
424
|
+
code: "MISSING_SERVICE_FRAMEWORK",
|
|
425
|
+
message: `Service "${name}" uses directory entrypoint "${serviceConfig.entrypoint}" but no framework could be detected in "${workspace}". Specify "framework" explicitly or use a file entrypoint.`,
|
|
426
|
+
serviceName: name
|
|
427
|
+
});
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
resolvedConfig = {
|
|
431
|
+
...resolvedConfig,
|
|
432
|
+
framework
|
|
433
|
+
};
|
|
434
|
+
} else {
|
|
435
|
+
const inferredRuntime = (0, import_utils.inferServiceRuntime)({
|
|
436
|
+
...serviceConfig,
|
|
437
|
+
entrypoint: resolvedEntrypoint.normalized
|
|
438
|
+
});
|
|
439
|
+
if (inferredRuntime) {
|
|
440
|
+
const inferredWorkspace = await inferWorkspaceFromNearestManifest({
|
|
441
|
+
fs,
|
|
442
|
+
entrypoint: resolvedEntrypoint.normalized,
|
|
443
|
+
runtime: inferredRuntime
|
|
444
|
+
});
|
|
445
|
+
const workspace = inferredWorkspace ?? import_path.posix.dirname(resolvedEntrypoint.normalized);
|
|
446
|
+
const detection = await detectFrameworkFromWorkspace({
|
|
447
|
+
fs,
|
|
448
|
+
workspace,
|
|
449
|
+
serviceName: name,
|
|
450
|
+
runtime: inferredRuntime
|
|
451
|
+
});
|
|
452
|
+
if (detection.framework) {
|
|
453
|
+
resolvedConfig = {
|
|
454
|
+
...resolvedConfig,
|
|
455
|
+
framework: detection.framework
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
}
|
|
417
459
|
}
|
|
418
|
-
resolvedConfig = {
|
|
419
|
-
...serviceConfig,
|
|
420
|
-
framework
|
|
421
|
-
};
|
|
422
460
|
}
|
|
423
461
|
const service = await resolveConfiguredService({
|
|
424
462
|
name,
|
package/dist/services/utils.d.ts
CHANGED
|
@@ -17,6 +17,18 @@ export declare function isStaticBuild(service: ResolvedService): boolean;
|
|
|
17
17
|
* rewrites for them — instead, we rely on the builder's own `routes[]`.
|
|
18
18
|
*/
|
|
19
19
|
export declare function isRouteOwningBuilder(service: ResolvedService): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Infer runtime from a framework slug.
|
|
22
|
+
*
|
|
23
|
+
* Examples:
|
|
24
|
+
* - `python` -> `python`
|
|
25
|
+
* - `fastapi` -> `python`
|
|
26
|
+
* - `express` -> `node`
|
|
27
|
+
*/
|
|
28
|
+
export declare function inferRuntimeFromFramework(framework: string | null | undefined): ServiceRuntime | undefined;
|
|
29
|
+
export declare function filterFrameworksByRuntime<T extends {
|
|
30
|
+
slug?: string | null;
|
|
31
|
+
}>(frameworks: readonly T[], runtime?: ServiceRuntime): T[];
|
|
20
32
|
/**
|
|
21
33
|
* Infer runtime from available service configuration.
|
|
22
34
|
*
|
package/dist/services/utils.js
CHANGED
|
@@ -19,9 +19,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var utils_exports = {};
|
|
20
20
|
__export(utils_exports, {
|
|
21
21
|
INTERNAL_SERVICE_PREFIX: () => INTERNAL_SERVICE_PREFIX,
|
|
22
|
+
filterFrameworksByRuntime: () => filterFrameworksByRuntime,
|
|
22
23
|
getBuilderForRuntime: () => getBuilderForRuntime,
|
|
23
24
|
getInternalServiceFunctionPath: () => getInternalServiceFunctionPath,
|
|
24
25
|
hasFile: () => hasFile,
|
|
26
|
+
inferRuntimeFromFramework: () => inferRuntimeFromFramework,
|
|
25
27
|
inferServiceRuntime: () => inferServiceRuntime,
|
|
26
28
|
isRouteOwningBuilder: () => isRouteOwningBuilder,
|
|
27
29
|
isStaticBuild: () => isStaticBuild,
|
|
@@ -54,19 +56,37 @@ function isStaticBuild(service) {
|
|
|
54
56
|
function isRouteOwningBuilder(service) {
|
|
55
57
|
return import_types.ROUTE_OWNING_BUILDERS.has(service.builder.use);
|
|
56
58
|
}
|
|
57
|
-
function
|
|
58
|
-
if (
|
|
59
|
-
return
|
|
59
|
+
function inferRuntimeFromFramework(framework) {
|
|
60
|
+
if (!framework) {
|
|
61
|
+
return void 0;
|
|
60
62
|
}
|
|
61
|
-
if (
|
|
62
|
-
return
|
|
63
|
+
if (framework in import_types.RUNTIME_BUILDERS) {
|
|
64
|
+
return framework;
|
|
63
65
|
}
|
|
64
|
-
if ((0, import_framework_helpers.isPythonFramework)(
|
|
66
|
+
if ((0, import_framework_helpers.isPythonFramework)(framework)) {
|
|
65
67
|
return "python";
|
|
66
68
|
}
|
|
67
|
-
if ((0, import_framework_helpers.isBackendFramework)(
|
|
69
|
+
if ((0, import_framework_helpers.isBackendFramework)(framework)) {
|
|
68
70
|
return "node";
|
|
69
71
|
}
|
|
72
|
+
return void 0;
|
|
73
|
+
}
|
|
74
|
+
function filterFrameworksByRuntime(frameworks, runtime) {
|
|
75
|
+
if (!runtime) {
|
|
76
|
+
return [...frameworks];
|
|
77
|
+
}
|
|
78
|
+
return frameworks.filter(
|
|
79
|
+
(framework) => inferRuntimeFromFramework(framework.slug) === runtime
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
function inferServiceRuntime(config) {
|
|
83
|
+
if (config.runtime && config.runtime in import_types.RUNTIME_BUILDERS) {
|
|
84
|
+
return config.runtime;
|
|
85
|
+
}
|
|
86
|
+
const frameworkRuntime = inferRuntimeFromFramework(config.framework);
|
|
87
|
+
if (frameworkRuntime) {
|
|
88
|
+
return frameworkRuntime;
|
|
89
|
+
}
|
|
70
90
|
if (config.builder) {
|
|
71
91
|
for (const [runtime, builderName] of Object.entries(import_types.RUNTIME_BUILDERS)) {
|
|
72
92
|
if (config.builder === builderName) {
|
|
@@ -105,9 +125,11 @@ async function readVercelConfig(fs) {
|
|
|
105
125
|
// Annotate the CommonJS export names for ESM import in node:
|
|
106
126
|
0 && (module.exports = {
|
|
107
127
|
INTERNAL_SERVICE_PREFIX,
|
|
128
|
+
filterFrameworksByRuntime,
|
|
108
129
|
getBuilderForRuntime,
|
|
109
130
|
getInternalServiceFunctionPath,
|
|
110
131
|
hasFile,
|
|
132
|
+
inferRuntimeFromFramework,
|
|
111
133
|
inferServiceRuntime,
|
|
112
134
|
isRouteOwningBuilder,
|
|
113
135
|
isStaticBuild,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/fs-detectors",
|
|
3
|
-
"version": "5.8.
|
|
3
|
+
"version": "5.8.16",
|
|
4
4
|
"description": "Vercel filesystem detectors",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"minimatch": "3.1.2",
|
|
21
21
|
"semver": "6.3.1",
|
|
22
22
|
"@vercel/error-utils": "2.0.3",
|
|
23
|
-
"@vercel/frameworks": "3.
|
|
24
|
-
"@vercel/routing-utils": "6.0.
|
|
23
|
+
"@vercel/frameworks": "3.20.0",
|
|
24
|
+
"@vercel/routing-utils": "6.0.2"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/glob": "7.2.0",
|