@vercel/fs-detectors 5.8.15 → 5.8.17
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.ts +1 -1
- package/dist/index.js +6 -0
- package/dist/services/auto-detect.js +3 -0
- package/dist/services/detect-services.d.ts +5 -1
- package/dist/services/detect-services.js +17 -0
- package/dist/services/get-services-builders.js +5 -1
- package/dist/services/resolve.js +61 -23
- package/dist/services/types.d.ts +0 -1
- package/dist/services/utils.d.ts +15 -0
- package/dist/services/utils.js +49 -7
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { detectBuilders, detectOutputDirectory, detectApiDirectory, detectApiExt
|
|
|
2
2
|
export { detectServices, generateServicesRoutes, } from './services/detect-services';
|
|
3
3
|
export { autoDetectServices } from './services/auto-detect';
|
|
4
4
|
export type { AutoDetectOptions, AutoDetectResult, } from './services/auto-detect';
|
|
5
|
-
export { isStaticBuild, isRouteOwningBuilder, INTERNAL_SERVICE_PREFIX, getInternalServiceFunctionPath, } from './services/utils';
|
|
5
|
+
export { isStaticBuild, isRouteOwningBuilder, INTERNAL_SERVICE_PREFIX, getInternalServiceFunctionPath, getInternalServiceCronPathPrefix, getInternalServiceWorkerPath, getInternalServiceWorkerPathPrefix, } from './services/utils';
|
|
6
6
|
export { getServicesBuilders } from './services/get-services-builders';
|
|
7
7
|
export type { DetectServicesOptions, DetectServicesResult, DetectServicesSource, ResolvedService, Service, ServicesRoutes, ServiceDetectionError, } from './services/types';
|
|
8
8
|
export { detectFileSystemAPI } from './detect-file-system-api';
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,10 @@ __export(src_exports, {
|
|
|
40
40
|
detectOutputDirectory: () => import_detect_builders.detectOutputDirectory,
|
|
41
41
|
detectServices: () => import_detect_services.detectServices,
|
|
42
42
|
generateServicesRoutes: () => import_detect_services.generateServicesRoutes,
|
|
43
|
+
getInternalServiceCronPathPrefix: () => import_utils.getInternalServiceCronPathPrefix,
|
|
43
44
|
getInternalServiceFunctionPath: () => import_utils.getInternalServiceFunctionPath,
|
|
45
|
+
getInternalServiceWorkerPath: () => import_utils.getInternalServiceWorkerPath,
|
|
46
|
+
getInternalServiceWorkerPathPrefix: () => import_utils.getInternalServiceWorkerPathPrefix,
|
|
44
47
|
getProjectPaths: () => import_get_project_paths.getProjectPaths,
|
|
45
48
|
getServicesBuilders: () => import_get_services_builders.getServicesBuilders,
|
|
46
49
|
getWorkspacePackagePaths: () => import_get_workspace_package_paths.getWorkspacePackagePaths,
|
|
@@ -96,7 +99,10 @@ var import_detect_instrumentation = require("./detect-instrumentation");
|
|
|
96
99
|
detectOutputDirectory,
|
|
97
100
|
detectServices,
|
|
98
101
|
generateServicesRoutes,
|
|
102
|
+
getInternalServiceCronPathPrefix,
|
|
99
103
|
getInternalServiceFunctionPath,
|
|
104
|
+
getInternalServiceWorkerPath,
|
|
105
|
+
getInternalServiceWorkerPathPrefix,
|
|
100
106
|
getProjectPaths,
|
|
101
107
|
getServicesBuilders,
|
|
102
108
|
getWorkspacePackagePaths,
|
|
@@ -112,6 +112,9 @@ async function detectServicesAtRoot(fs, rootFramework) {
|
|
|
112
112
|
if (backendResult.error) {
|
|
113
113
|
return { services: null, errors: [backendResult.error] };
|
|
114
114
|
}
|
|
115
|
+
if (Object.keys(backendResult.services).length === 0) {
|
|
116
|
+
return { services: null, errors: [] };
|
|
117
|
+
}
|
|
115
118
|
Object.assign(services, backendResult.services);
|
|
116
119
|
return { services, errors: [] };
|
|
117
120
|
}
|
|
@@ -26,6 +26,10 @@ export declare function detectServices(options: DetectServicesOptions): Promise<
|
|
|
26
26
|
* Builders that provide their own routing (`@vercel/next`, `@vercel/backends`,
|
|
27
27
|
* Build Output API builders, etc.) are not given synthetic routes here.
|
|
28
28
|
*
|
|
29
|
-
* -
|
|
29
|
+
* - Worker services:
|
|
30
|
+
* Internal queue callback routes under `/_svc/{serviceName}/workers/{entry}/{handler}`
|
|
31
|
+
* that rewrite to `/_svc/{serviceName}/index`.
|
|
32
|
+
*
|
|
33
|
+
* - Cron services: TODO - internal routes under `/_svc/`
|
|
30
34
|
*/
|
|
31
35
|
export declare function generateServicesRoutes(services: ResolvedService[]): ServicesRoutes;
|
|
@@ -148,8 +148,25 @@ function generateServicesRoutes(services) {
|
|
|
148
148
|
continue;
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
|
+
const workerServices = services.filter((s) => s.type === "worker");
|
|
152
|
+
for (const service of workerServices) {
|
|
153
|
+
const workerEntrypoint = service.entrypoint || service.builder.src || "index";
|
|
154
|
+
const workerPath = (0, import_utils.getInternalServiceWorkerPath)(
|
|
155
|
+
service.name,
|
|
156
|
+
workerEntrypoint
|
|
157
|
+
);
|
|
158
|
+
const functionPath = (0, import_utils.getInternalServiceFunctionPath)(service.name);
|
|
159
|
+
workers.push({
|
|
160
|
+
src: `^${escapeRegex(workerPath)}$`,
|
|
161
|
+
dest: functionPath,
|
|
162
|
+
check: true
|
|
163
|
+
});
|
|
164
|
+
}
|
|
151
165
|
return { rewrites, defaults, crons, workers };
|
|
152
166
|
}
|
|
167
|
+
function escapeRegex(str) {
|
|
168
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
169
|
+
}
|
|
153
170
|
function getWebRoutePrefixes(services) {
|
|
154
171
|
const unique = /* @__PURE__ */ new Set();
|
|
155
172
|
for (const service of services) {
|
|
@@ -84,7 +84,11 @@ async function getServicesBuilders(options) {
|
|
|
84
84
|
warnings: warningResponses,
|
|
85
85
|
defaultRoutes: result.routes.defaults.length > 0 ? result.routes.defaults : null,
|
|
86
86
|
redirectRoutes: [],
|
|
87
|
-
rewriteRoutes: result.routes.rewrites.length > 0
|
|
87
|
+
rewriteRoutes: result.routes.rewrites.length > 0 || result.routes.workers.length > 0 || result.routes.crons.length > 0 ? [
|
|
88
|
+
...result.routes.rewrites,
|
|
89
|
+
...result.routes.workers,
|
|
90
|
+
...result.routes.crons
|
|
91
|
+
] : null,
|
|
88
92
|
errorRoutes: [],
|
|
89
93
|
services: result.services
|
|
90
94
|
};
|
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/types.d.ts
CHANGED
package/dist/services/utils.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ export declare function hasFile(fs: DetectorFilesystem, filePath: string): Promi
|
|
|
6
6
|
*/
|
|
7
7
|
export declare const INTERNAL_SERVICE_PREFIX = "/_svc";
|
|
8
8
|
export declare function getInternalServiceFunctionPath(serviceName: string): string;
|
|
9
|
+
export declare function getInternalServiceWorkerPathPrefix(serviceName: string): string;
|
|
10
|
+
export declare function getInternalServiceCronPathPrefix(serviceName: string): string;
|
|
11
|
+
export declare function getInternalServiceWorkerPath(serviceName: string, entrypoint: string, handler?: string): string;
|
|
9
12
|
export declare function getBuilderForRuntime(runtime: ServiceRuntime): string;
|
|
10
13
|
export declare function isStaticBuild(service: ResolvedService): boolean;
|
|
11
14
|
/**
|
|
@@ -17,6 +20,18 @@ export declare function isStaticBuild(service: ResolvedService): boolean;
|
|
|
17
20
|
* rewrites for them — instead, we rely on the builder's own `routes[]`.
|
|
18
21
|
*/
|
|
19
22
|
export declare function isRouteOwningBuilder(service: ResolvedService): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Infer runtime from a framework slug.
|
|
25
|
+
*
|
|
26
|
+
* Examples:
|
|
27
|
+
* - `python` -> `python`
|
|
28
|
+
* - `fastapi` -> `python`
|
|
29
|
+
* - `express` -> `node`
|
|
30
|
+
*/
|
|
31
|
+
export declare function inferRuntimeFromFramework(framework: string | null | undefined): ServiceRuntime | undefined;
|
|
32
|
+
export declare function filterFrameworksByRuntime<T extends {
|
|
33
|
+
slug?: string | null;
|
|
34
|
+
}>(frameworks: readonly T[], runtime?: ServiceRuntime): T[];
|
|
20
35
|
/**
|
|
21
36
|
* Infer runtime from available service configuration.
|
|
22
37
|
*
|
package/dist/services/utils.js
CHANGED
|
@@ -19,9 +19,14 @@ 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,
|
|
24
|
+
getInternalServiceCronPathPrefix: () => getInternalServiceCronPathPrefix,
|
|
23
25
|
getInternalServiceFunctionPath: () => getInternalServiceFunctionPath,
|
|
26
|
+
getInternalServiceWorkerPath: () => getInternalServiceWorkerPath,
|
|
27
|
+
getInternalServiceWorkerPathPrefix: () => getInternalServiceWorkerPathPrefix,
|
|
24
28
|
hasFile: () => hasFile,
|
|
29
|
+
inferRuntimeFromFramework: () => inferRuntimeFromFramework,
|
|
25
30
|
inferServiceRuntime: () => inferServiceRuntime,
|
|
26
31
|
isRouteOwningBuilder: () => isRouteOwningBuilder,
|
|
27
32
|
isStaticBuild: () => isStaticBuild,
|
|
@@ -41,6 +46,20 @@ const INTERNAL_SERVICE_PREFIX = "/_svc";
|
|
|
41
46
|
function getInternalServiceFunctionPath(serviceName) {
|
|
42
47
|
return `${INTERNAL_SERVICE_PREFIX}/${serviceName}/index`;
|
|
43
48
|
}
|
|
49
|
+
function normalizeInternalServiceEntrypoint(entrypoint) {
|
|
50
|
+
const normalized = entrypoint.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\.[^/.]+$/, "");
|
|
51
|
+
return normalized || "index";
|
|
52
|
+
}
|
|
53
|
+
function getInternalServiceWorkerPathPrefix(serviceName) {
|
|
54
|
+
return `${INTERNAL_SERVICE_PREFIX}/${serviceName}/workers`;
|
|
55
|
+
}
|
|
56
|
+
function getInternalServiceCronPathPrefix(serviceName) {
|
|
57
|
+
return `${INTERNAL_SERVICE_PREFIX}/${serviceName}/crons`;
|
|
58
|
+
}
|
|
59
|
+
function getInternalServiceWorkerPath(serviceName, entrypoint, handler = "worker") {
|
|
60
|
+
const normalizedEntrypoint = normalizeInternalServiceEntrypoint(entrypoint);
|
|
61
|
+
return `${getInternalServiceWorkerPathPrefix(serviceName)}/${normalizedEntrypoint}/${handler}`;
|
|
62
|
+
}
|
|
44
63
|
function getBuilderForRuntime(runtime) {
|
|
45
64
|
const builder = import_types.RUNTIME_BUILDERS[runtime];
|
|
46
65
|
if (!builder) {
|
|
@@ -54,19 +73,37 @@ function isStaticBuild(service) {
|
|
|
54
73
|
function isRouteOwningBuilder(service) {
|
|
55
74
|
return import_types.ROUTE_OWNING_BUILDERS.has(service.builder.use);
|
|
56
75
|
}
|
|
57
|
-
function
|
|
58
|
-
if (
|
|
59
|
-
return
|
|
76
|
+
function inferRuntimeFromFramework(framework) {
|
|
77
|
+
if (!framework) {
|
|
78
|
+
return void 0;
|
|
60
79
|
}
|
|
61
|
-
if (
|
|
62
|
-
return
|
|
80
|
+
if (framework in import_types.RUNTIME_BUILDERS) {
|
|
81
|
+
return framework;
|
|
63
82
|
}
|
|
64
|
-
if ((0, import_framework_helpers.isPythonFramework)(
|
|
83
|
+
if ((0, import_framework_helpers.isPythonFramework)(framework)) {
|
|
65
84
|
return "python";
|
|
66
85
|
}
|
|
67
|
-
if ((0, import_framework_helpers.isBackendFramework)(
|
|
86
|
+
if ((0, import_framework_helpers.isBackendFramework)(framework)) {
|
|
68
87
|
return "node";
|
|
69
88
|
}
|
|
89
|
+
return void 0;
|
|
90
|
+
}
|
|
91
|
+
function filterFrameworksByRuntime(frameworks, runtime) {
|
|
92
|
+
if (!runtime) {
|
|
93
|
+
return [...frameworks];
|
|
94
|
+
}
|
|
95
|
+
return frameworks.filter(
|
|
96
|
+
(framework) => inferRuntimeFromFramework(framework.slug) === runtime
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
function inferServiceRuntime(config) {
|
|
100
|
+
if (config.runtime && config.runtime in import_types.RUNTIME_BUILDERS) {
|
|
101
|
+
return config.runtime;
|
|
102
|
+
}
|
|
103
|
+
const frameworkRuntime = inferRuntimeFromFramework(config.framework);
|
|
104
|
+
if (frameworkRuntime) {
|
|
105
|
+
return frameworkRuntime;
|
|
106
|
+
}
|
|
70
107
|
if (config.builder) {
|
|
71
108
|
for (const [runtime, builderName] of Object.entries(import_types.RUNTIME_BUILDERS)) {
|
|
72
109
|
if (config.builder === builderName) {
|
|
@@ -105,9 +142,14 @@ async function readVercelConfig(fs) {
|
|
|
105
142
|
// Annotate the CommonJS export names for ESM import in node:
|
|
106
143
|
0 && (module.exports = {
|
|
107
144
|
INTERNAL_SERVICE_PREFIX,
|
|
145
|
+
filterFrameworksByRuntime,
|
|
108
146
|
getBuilderForRuntime,
|
|
147
|
+
getInternalServiceCronPathPrefix,
|
|
109
148
|
getInternalServiceFunctionPath,
|
|
149
|
+
getInternalServiceWorkerPath,
|
|
150
|
+
getInternalServiceWorkerPathPrefix,
|
|
110
151
|
hasFile,
|
|
152
|
+
inferRuntimeFromFramework,
|
|
111
153
|
inferServiceRuntime,
|
|
112
154
|
isRouteOwningBuilder,
|
|
113
155
|
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.17",
|
|
4
4
|
"description": "Vercel filesystem detectors",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"json5": "2.2.2",
|
|
20
20
|
"minimatch": "3.1.2",
|
|
21
21
|
"semver": "6.3.1",
|
|
22
|
+
"@vercel/routing-utils": "6.0.2",
|
|
22
23
|
"@vercel/error-utils": "2.0.3",
|
|
23
|
-
"@vercel/frameworks": "3.
|
|
24
|
-
"@vercel/routing-utils": "6.0.1"
|
|
24
|
+
"@vercel/frameworks": "3.20.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/glob": "7.2.0",
|