@vercel/fs-detectors 5.8.3 → 5.8.5
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/detect-builders.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/services/detect-services.d.ts +12 -2
- package/dist/services/detect-services.js +20 -2
- package/dist/services/resolve.js +28 -2
- package/dist/services/types.d.ts +13 -0
- package/dist/services/types.js +6 -0
- package/dist/services/utils.d.ts +9 -0
- package/dist/services/utils.js +5 -0
- package/package.json +4 -4
package/dist/detect-builders.js
CHANGED
|
@@ -527,7 +527,7 @@ function checkUnusedFunctions(frontendBuilder, usedFunctions, options) {
|
|
|
527
527
|
}
|
|
528
528
|
}
|
|
529
529
|
}
|
|
530
|
-
if (frontendBuilder && ((0, import_is_official_runtime.isOfficialRuntime)("express", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("hono", frontendBuilder.use))) {
|
|
530
|
+
if (frontendBuilder && ((0, import_is_official_runtime.isOfficialRuntime)("express", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("hono", frontendBuilder.use) || (0, import_is_official_runtime.isOfficialRuntime)("backends", frontendBuilder.use))) {
|
|
531
531
|
const validFilenames = [
|
|
532
532
|
"app",
|
|
533
533
|
"index",
|
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 } from './services/utils';
|
|
5
|
+
export { isStaticBuild, isRouteOwningBuilder } from './services/utils';
|
|
6
6
|
export { getServicesBuilders } from './services/get-services-builders';
|
|
7
7
|
export type { DetectServicesOptions, DetectServicesResult, ResolvedService, Service, ServicesRoutes, ServiceDetectionError, } from './services/types';
|
|
8
8
|
export { detectFileSystemAPI } from './detect-file-system-api';
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,7 @@ __export(src_exports, {
|
|
|
44
44
|
getWorkspacePackagePaths: () => import_get_workspace_package_paths.getWorkspacePackagePaths,
|
|
45
45
|
getWorkspaces: () => import_get_workspaces.getWorkspaces,
|
|
46
46
|
isOfficialRuntime: () => import_is_official_runtime.isOfficialRuntime,
|
|
47
|
+
isRouteOwningBuilder: () => import_utils.isRouteOwningBuilder,
|
|
47
48
|
isStaticBuild: () => import_utils.isStaticBuild,
|
|
48
49
|
isStaticRuntime: () => import_is_official_runtime.isStaticRuntime,
|
|
49
50
|
monorepoManagers: () => import_monorepo_managers.monorepoManagers,
|
|
@@ -97,6 +98,7 @@ var import_detect_instrumentation = require("./detect-instrumentation");
|
|
|
97
98
|
getWorkspacePackagePaths,
|
|
98
99
|
getWorkspaces,
|
|
99
100
|
isOfficialRuntime,
|
|
101
|
+
isRouteOwningBuilder,
|
|
100
102
|
isStaticBuild,
|
|
101
103
|
isStaticRuntime,
|
|
102
104
|
monorepoManagers,
|
|
@@ -13,8 +13,18 @@ export declare function detectServices(options: DetectServicesOptions): Promise<
|
|
|
13
13
|
* routes match before broader ones. For example, `/api/users` must be checked
|
|
14
14
|
* before `/api`, which must be checked before the catch-all `/`.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Services routing only generates *synthetic* routes for builders that do not
|
|
17
|
+
* provide their own route tables:
|
|
18
|
+
*
|
|
19
|
+
* - **Static/SPA services** (`@vercel/static-build`, `@vercel/static`):
|
|
20
|
+
* SPA fallback routes to index.html under the service prefix.
|
|
21
|
+
*
|
|
22
|
+
* - **Runtime services** (`@vercel/python`, `@vercel/go`, `@vercel/ruby`, etc.):
|
|
23
|
+
* Prefix rewrites to the function entrypoint with `check: true`.
|
|
24
|
+
*
|
|
25
|
+
* Builders that provide their own routing (`@vercel/next`, `@vercel/backends`,
|
|
26
|
+
* Build Output API builders, etc.) are not given synthetic routes here.
|
|
27
|
+
*
|
|
18
28
|
* - Cron/Worker services: TODO - internal routes under `/_svc/`
|
|
19
29
|
*/
|
|
20
30
|
export declare function generateServicesRoutes(services: ResolvedService[]): ServicesRoutes;
|
|
@@ -22,6 +22,7 @@ __export(detect_services_exports, {
|
|
|
22
22
|
generateServicesRoutes: () => generateServicesRoutes
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(detect_services_exports);
|
|
25
|
+
var import_types = require("./types");
|
|
25
26
|
var import_utils = require("./utils");
|
|
26
27
|
var import_resolve = require("./resolve");
|
|
27
28
|
var import_auto_detect = require("./auto-detect");
|
|
@@ -85,12 +86,26 @@ function generateServicesRoutes(services) {
|
|
|
85
86
|
const defaults = [];
|
|
86
87
|
const crons = [];
|
|
87
88
|
const workers = [];
|
|
89
|
+
const entrypointExtensions = Object.keys(import_types.ENTRYPOINT_EXTENSIONS).sort(
|
|
90
|
+
(a, b) => b.length - a.length
|
|
91
|
+
);
|
|
92
|
+
const stripEntrypointExtension = (entrypoint) => {
|
|
93
|
+
for (const ext of entrypointExtensions) {
|
|
94
|
+
if (entrypoint.endsWith(ext)) {
|
|
95
|
+
return entrypoint.slice(0, -ext.length);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return entrypoint;
|
|
99
|
+
};
|
|
88
100
|
const sortedWebServices = services.filter(
|
|
89
101
|
(s) => s.type === "web" && typeof s.routePrefix === "string"
|
|
90
102
|
).sort((a, b) => b.routePrefix.length - a.routePrefix.length);
|
|
91
103
|
for (const service of sortedWebServices) {
|
|
92
104
|
const { routePrefix } = service;
|
|
93
105
|
const normalizedPrefix = routePrefix.slice(1);
|
|
106
|
+
if ((0, import_utils.isRouteOwningBuilder)(service)) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
94
109
|
if ((0, import_utils.isStaticBuild)(service)) {
|
|
95
110
|
if (routePrefix === "/") {
|
|
96
111
|
defaults.push({ handle: "filesystem" });
|
|
@@ -101,9 +116,10 @@ function generateServicesRoutes(services) {
|
|
|
101
116
|
dest: `/${normalizedPrefix}/index.html`
|
|
102
117
|
});
|
|
103
118
|
}
|
|
104
|
-
} else {
|
|
119
|
+
} else if (service.runtime) {
|
|
105
120
|
const builderSrc = service.builder.src || routePrefix;
|
|
106
|
-
const
|
|
121
|
+
const extensionless = stripEntrypointExtension(builderSrc);
|
|
122
|
+
const functionPath = extensionless.startsWith("/") ? extensionless : `/${extensionless}`;
|
|
107
123
|
if (routePrefix === "/") {
|
|
108
124
|
defaults.push({ src: "^/(.*)$", dest: functionPath, check: true });
|
|
109
125
|
} else {
|
|
@@ -113,6 +129,8 @@ function generateServicesRoutes(services) {
|
|
|
113
129
|
check: true
|
|
114
130
|
});
|
|
115
131
|
}
|
|
132
|
+
} else {
|
|
133
|
+
continue;
|
|
116
134
|
}
|
|
117
135
|
}
|
|
118
136
|
return { rewrites, defaults, crons, workers };
|
package/dist/services/resolve.js
CHANGED
|
@@ -39,6 +39,13 @@ var import_utils = require("./utils");
|
|
|
39
39
|
var import_frameworks = __toESM(require("@vercel/frameworks"));
|
|
40
40
|
const frameworksBySlug = new Map(import_frameworks.default.map((f) => [f.slug, f]));
|
|
41
41
|
const SERVICE_NAME_REGEX = /^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
|
|
42
|
+
function normalizeRoutePrefix(routePrefix) {
|
|
43
|
+
let normalized = routePrefix.startsWith("/") ? routePrefix : `/${routePrefix}`;
|
|
44
|
+
if (normalized !== "/" && normalized.endsWith("/")) {
|
|
45
|
+
normalized = normalized.slice(0, -1);
|
|
46
|
+
}
|
|
47
|
+
return normalized || "/";
|
|
48
|
+
}
|
|
42
49
|
function validateServiceConfig(name, config) {
|
|
43
50
|
if (!SERVICE_NAME_REGEX.test(name)) {
|
|
44
51
|
return {
|
|
@@ -141,10 +148,10 @@ function resolveConfiguredService(name, config, group) {
|
|
|
141
148
|
}
|
|
142
149
|
const routePrefix = type === "web" && config.routePrefix ? config.routePrefix.startsWith("/") ? config.routePrefix : `/${config.routePrefix}` : void 0;
|
|
143
150
|
const isRoot = workspace === ".";
|
|
144
|
-
if (!isRoot
|
|
151
|
+
if (!isRoot) {
|
|
145
152
|
builderSrc = import_path.posix.join(workspace, builderSrc);
|
|
146
153
|
}
|
|
147
|
-
const builderConfig = {};
|
|
154
|
+
const builderConfig = { zeroConfig: true };
|
|
148
155
|
if (config.memory)
|
|
149
156
|
builderConfig.memory = config.memory;
|
|
150
157
|
if (config.maxDuration)
|
|
@@ -159,6 +166,9 @@ function resolveConfiguredService(name, config, group) {
|
|
|
159
166
|
const stripped = routePrefix.startsWith("/") ? routePrefix.slice(1) : routePrefix;
|
|
160
167
|
builderConfig.routePrefix = stripped || ".";
|
|
161
168
|
}
|
|
169
|
+
if (workspace && workspace !== ".") {
|
|
170
|
+
builderConfig.workspace = workspace;
|
|
171
|
+
}
|
|
162
172
|
if (config.framework) {
|
|
163
173
|
builderConfig.framework = config.framework;
|
|
164
174
|
}
|
|
@@ -186,6 +196,7 @@ function resolveConfiguredService(name, config, group) {
|
|
|
186
196
|
function resolveAllConfiguredServices(services) {
|
|
187
197
|
const resolved = [];
|
|
188
198
|
const errors = [];
|
|
199
|
+
const webServicesByRoutePrefix = /* @__PURE__ */ new Map();
|
|
189
200
|
for (const name of Object.keys(services)) {
|
|
190
201
|
const serviceConfig = services[name];
|
|
191
202
|
const validationError = validateServiceConfig(name, serviceConfig);
|
|
@@ -194,6 +205,21 @@ function resolveAllConfiguredServices(services) {
|
|
|
194
205
|
continue;
|
|
195
206
|
}
|
|
196
207
|
const service = resolveConfiguredService(name, serviceConfig);
|
|
208
|
+
if (service.type === "web" && typeof service.routePrefix === "string") {
|
|
209
|
+
const normalizedRoutePrefix = normalizeRoutePrefix(service.routePrefix);
|
|
210
|
+
const existingServiceName = webServicesByRoutePrefix.get(
|
|
211
|
+
normalizedRoutePrefix
|
|
212
|
+
);
|
|
213
|
+
if (existingServiceName) {
|
|
214
|
+
errors.push({
|
|
215
|
+
code: "DUPLICATE_ROUTE_PREFIX",
|
|
216
|
+
message: `Web services "${existingServiceName}" and "${name}" cannot share routePrefix "${normalizedRoutePrefix}".`,
|
|
217
|
+
serviceName: name
|
|
218
|
+
});
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
webServicesByRoutePrefix.set(normalizedRoutePrefix, name);
|
|
222
|
+
}
|
|
197
223
|
resolved.push(service);
|
|
198
224
|
}
|
|
199
225
|
return { services: resolved, errors };
|
package/dist/services/types.d.ts
CHANGED
|
@@ -56,3 +56,16 @@ export declare const ENTRYPOINT_EXTENSIONS: Record<string, ServiceRuntime>;
|
|
|
56
56
|
* These don't have a "runtime" - they just build to static files.
|
|
57
57
|
*/
|
|
58
58
|
export declare const STATIC_BUILDERS: Set<string>;
|
|
59
|
+
/**
|
|
60
|
+
* Builders that produce their own full route table with handle phases
|
|
61
|
+
* (filesystem, miss, rewrite, hit, error).
|
|
62
|
+
*
|
|
63
|
+
* In services mode we generally avoid generating synthetic catch-all routes
|
|
64
|
+
* for builders that provide their own routing. At service-detection time we
|
|
65
|
+
* only have the builder "use" string (not the loaded module), so this is an
|
|
66
|
+
* explicit allow-list for known route-table builders.
|
|
67
|
+
*
|
|
68
|
+
* NOTE: This is an explicit positive set because we can't check
|
|
69
|
+
* `builder.version` at service detection time.
|
|
70
|
+
*/
|
|
71
|
+
export declare const ROUTE_OWNING_BUILDERS: Set<string>;
|
package/dist/services/types.js
CHANGED
|
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var types_exports = {};
|
|
20
20
|
__export(types_exports, {
|
|
21
21
|
ENTRYPOINT_EXTENSIONS: () => ENTRYPOINT_EXTENSIONS,
|
|
22
|
+
ROUTE_OWNING_BUILDERS: () => ROUTE_OWNING_BUILDERS,
|
|
22
23
|
RUNTIME_BUILDERS: () => RUNTIME_BUILDERS,
|
|
23
24
|
STATIC_BUILDERS: () => STATIC_BUILDERS
|
|
24
25
|
});
|
|
@@ -46,9 +47,14 @@ const STATIC_BUILDERS = /* @__PURE__ */ new Set([
|
|
|
46
47
|
"@vercel/static-build",
|
|
47
48
|
"@vercel/static"
|
|
48
49
|
]);
|
|
50
|
+
const ROUTE_OWNING_BUILDERS = /* @__PURE__ */ new Set([
|
|
51
|
+
"@vercel/next",
|
|
52
|
+
"@vercel/backends"
|
|
53
|
+
]);
|
|
49
54
|
// Annotate the CommonJS export names for ESM import in node:
|
|
50
55
|
0 && (module.exports = {
|
|
51
56
|
ENTRYPOINT_EXTENSIONS,
|
|
57
|
+
ROUTE_OWNING_BUILDERS,
|
|
52
58
|
RUNTIME_BUILDERS,
|
|
53
59
|
STATIC_BUILDERS
|
|
54
60
|
});
|
package/dist/services/utils.d.ts
CHANGED
|
@@ -2,6 +2,15 @@ import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
|
2
2
|
import type { ServiceRuntime, ExperimentalServices, ServiceDetectionError, ResolvedService } from './types';
|
|
3
3
|
export declare function getBuilderForRuntime(runtime: ServiceRuntime): string;
|
|
4
4
|
export declare function isStaticBuild(service: ResolvedService): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Determines if a service uses a "route-owning" builder.
|
|
7
|
+
*
|
|
8
|
+
* Route-owning builders (e.g., `@vercel/next`, `@vercel/backends`) produce
|
|
9
|
+
* their own full route table with handle phases (filesystem, miss, rewrite,
|
|
10
|
+
* hit, error). The services system should NOT generate synthetic catch-all
|
|
11
|
+
* rewrites for them — instead, we rely on the builder's own `routes[]`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isRouteOwningBuilder(service: ResolvedService): boolean;
|
|
5
14
|
/**
|
|
6
15
|
* Infer runtime from available service configuration.
|
|
7
16
|
*
|
package/dist/services/utils.js
CHANGED
|
@@ -20,6 +20,7 @@ var utils_exports = {};
|
|
|
20
20
|
__export(utils_exports, {
|
|
21
21
|
getBuilderForRuntime: () => getBuilderForRuntime,
|
|
22
22
|
inferServiceRuntime: () => inferServiceRuntime,
|
|
23
|
+
isRouteOwningBuilder: () => isRouteOwningBuilder,
|
|
23
24
|
isStaticBuild: () => isStaticBuild,
|
|
24
25
|
readVercelConfig: () => readVercelConfig
|
|
25
26
|
});
|
|
@@ -36,6 +37,9 @@ function getBuilderForRuntime(runtime) {
|
|
|
36
37
|
function isStaticBuild(service) {
|
|
37
38
|
return import_types.STATIC_BUILDERS.has(service.builder.use);
|
|
38
39
|
}
|
|
40
|
+
function isRouteOwningBuilder(service) {
|
|
41
|
+
return import_types.ROUTE_OWNING_BUILDERS.has(service.builder.use);
|
|
42
|
+
}
|
|
39
43
|
function inferServiceRuntime(config) {
|
|
40
44
|
if (config.runtime && config.runtime in import_types.RUNTIME_BUILDERS) {
|
|
41
45
|
return config.runtime;
|
|
@@ -85,6 +89,7 @@ async function readVercelConfig(fs) {
|
|
|
85
89
|
0 && (module.exports = {
|
|
86
90
|
getBuilderForRuntime,
|
|
87
91
|
inferServiceRuntime,
|
|
92
|
+
isRouteOwningBuilder,
|
|
88
93
|
isStaticBuild,
|
|
89
94
|
readVercelConfig
|
|
90
95
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/fs-detectors",
|
|
3
|
-
"version": "5.8.
|
|
3
|
+
"version": "5.8.5",
|
|
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/
|
|
22
|
+
"@vercel/routing-utils": "5.3.2",
|
|
23
23
|
"@vercel/frameworks": "3.17.1",
|
|
24
|
-
"@vercel/
|
|
24
|
+
"@vercel/error-utils": "2.0.3"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/glob": "7.2.0",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@types/semver": "7.3.10",
|
|
33
33
|
"jest-junit": "16.0.0",
|
|
34
34
|
"typescript": "4.9.5",
|
|
35
|
-
"@vercel/build-utils": "13.3.
|
|
35
|
+
"@vercel/build-utils": "13.3.5"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "node ../../utils/build.mjs",
|