@vercel/fs-detectors 5.7.21 → 5.8.0
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.d.ts +2 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/services/auto-detect.d.ts +39 -0
- package/dist/services/auto-detect.js +228 -0
- package/dist/services/detect-services.d.ts +6 -5
- package/dist/services/detect-services.js +45 -24
- package/dist/services/resolve.js +8 -1
- package/dist/services/types.d.ts +6 -24
- package/dist/services/utils.d.ts +2 -1
- package/dist/services/utils.js +5 -0
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Route } from '@vercel/routing-utils';
|
|
2
|
-
import type { PackageJson, Builder, BuilderFunctions, ProjectSettings } from '@vercel/build-utils';
|
|
2
|
+
import type { PackageJson, Builder, BuilderFunctions, ProjectSettings, Service } from '@vercel/build-utils';
|
|
3
3
|
/**
|
|
4
4
|
* Pattern for finding all supported middleware files.
|
|
5
5
|
*/
|
|
@@ -41,4 +41,5 @@ export declare function detectBuilders(files: string[], pkg?: PackageJson | unde
|
|
|
41
41
|
redirectRoutes: Route[] | null;
|
|
42
42
|
rewriteRoutes: Route[] | null;
|
|
43
43
|
errorRoutes: Route[] | null;
|
|
44
|
+
services?: Service[];
|
|
44
45
|
}>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { detectBuilders, detectOutputDirectory, detectApiDirectory, detectApiExtensions, type Options as DetectBuildersOptions, } from './detect-builders';
|
|
2
2
|
export { detectServices, generateServicesRoutes, } from './services/detect-services';
|
|
3
|
+
export { autoDetectServices } from './services/auto-detect';
|
|
4
|
+
export type { AutoDetectOptions, AutoDetectResult, } from './services/auto-detect';
|
|
5
|
+
export { isStaticBuild } from './services/utils';
|
|
3
6
|
export { getServicesBuilders } from './services/get-services-builders';
|
|
4
7
|
export type { DetectServicesOptions, DetectServicesResult, ResolvedService, ServicesRoutes, ServiceDetectionError, } from './services/types';
|
|
5
8
|
export { detectFileSystemAPI } from './detect-file-system-api';
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(src_exports, {
|
|
|
26
26
|
REGEX_NON_VERCEL_PLATFORM_FILES: () => import_detect_builders2.REGEX_NON_VERCEL_PLATFORM_FILES,
|
|
27
27
|
Workspace: () => import_get_workspaces.Workspace,
|
|
28
28
|
WorkspaceType: () => import_get_workspaces.WorkspaceType,
|
|
29
|
+
autoDetectServices: () => import_auto_detect.autoDetectServices,
|
|
29
30
|
detectApiDirectory: () => import_detect_builders.detectApiDirectory,
|
|
30
31
|
detectApiExtensions: () => import_detect_builders.detectApiExtensions,
|
|
31
32
|
detectBuilders: () => import_detect_builders.detectBuilders,
|
|
@@ -43,6 +44,7 @@ __export(src_exports, {
|
|
|
43
44
|
getWorkspacePackagePaths: () => import_get_workspace_package_paths.getWorkspacePackagePaths,
|
|
44
45
|
getWorkspaces: () => import_get_workspaces.getWorkspaces,
|
|
45
46
|
isOfficialRuntime: () => import_is_official_runtime.isOfficialRuntime,
|
|
47
|
+
isStaticBuild: () => import_utils.isStaticBuild,
|
|
46
48
|
isStaticRuntime: () => import_is_official_runtime.isStaticRuntime,
|
|
47
49
|
monorepoManagers: () => import_monorepo_managers.monorepoManagers,
|
|
48
50
|
packageManagers: () => import_package_managers.packageManagers,
|
|
@@ -51,6 +53,8 @@ __export(src_exports, {
|
|
|
51
53
|
module.exports = __toCommonJS(src_exports);
|
|
52
54
|
var import_detect_builders = require("./detect-builders");
|
|
53
55
|
var import_detect_services = require("./services/detect-services");
|
|
56
|
+
var import_auto_detect = require("./services/auto-detect");
|
|
57
|
+
var import_utils = require("./services/utils");
|
|
54
58
|
var import_get_services_builders = require("./services/get-services-builders");
|
|
55
59
|
var import_detect_file_system_api = require("./detect-file-system-api");
|
|
56
60
|
var import_detect_framework = require("./detect-framework");
|
|
@@ -75,6 +79,7 @@ var import_detect_instrumentation = require("./detect-instrumentation");
|
|
|
75
79
|
REGEX_NON_VERCEL_PLATFORM_FILES,
|
|
76
80
|
Workspace,
|
|
77
81
|
WorkspaceType,
|
|
82
|
+
autoDetectServices,
|
|
78
83
|
detectApiDirectory,
|
|
79
84
|
detectApiExtensions,
|
|
80
85
|
detectBuilders,
|
|
@@ -92,6 +97,7 @@ var import_detect_instrumentation = require("./detect-instrumentation");
|
|
|
92
97
|
getWorkspacePackagePaths,
|
|
93
98
|
getWorkspaces,
|
|
94
99
|
isOfficialRuntime,
|
|
100
|
+
isStaticBuild,
|
|
95
101
|
isStaticRuntime,
|
|
96
102
|
monorepoManagers,
|
|
97
103
|
packageManagers,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
2
|
+
import type { ExperimentalServices, ServiceDetectionError } from './types';
|
|
3
|
+
export interface AutoDetectOptions {
|
|
4
|
+
fs: DetectorFilesystem;
|
|
5
|
+
}
|
|
6
|
+
export interface AutoDetectResult {
|
|
7
|
+
services: ExperimentalServices | null;
|
|
8
|
+
errors: ServiceDetectionError[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Auto-detect services when experimentalServices is not configured.
|
|
12
|
+
*
|
|
13
|
+
* Scans the project for frameworks, supporting multiple layouts:
|
|
14
|
+
*
|
|
15
|
+
* Frontend at root, backend in backend/:
|
|
16
|
+
* project/
|
|
17
|
+
* ├── package.json
|
|
18
|
+
* └── backend/
|
|
19
|
+
*
|
|
20
|
+
* Frontend in frontend/, backend in backend/:
|
|
21
|
+
* project/
|
|
22
|
+
* ├── frontend/
|
|
23
|
+
* └── backend/
|
|
24
|
+
*
|
|
25
|
+
* Frontend in frontend/, backend in services/{service-name}/:
|
|
26
|
+
* project/
|
|
27
|
+
* ├── frontend/
|
|
28
|
+
* └── services/
|
|
29
|
+
* ├── service-a/
|
|
30
|
+
* └── service-b/
|
|
31
|
+
*
|
|
32
|
+
* Frontend in apps/web/ monorepo, backend in services/{service-name}/:
|
|
33
|
+
* project/
|
|
34
|
+
* ├── apps/web/
|
|
35
|
+
* └── services/
|
|
36
|
+
* ├── service-a/
|
|
37
|
+
* └── service-b/
|
|
38
|
+
*/
|
|
39
|
+
export declare function autoDetectServices(options: AutoDetectOptions): Promise<AutoDetectResult>;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var auto_detect_exports = {};
|
|
30
|
+
__export(auto_detect_exports, {
|
|
31
|
+
autoDetectServices: () => autoDetectServices
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(auto_detect_exports);
|
|
34
|
+
var import_detect_framework = require("../detect-framework");
|
|
35
|
+
var import_frameworks = __toESM(require("@vercel/frameworks"));
|
|
36
|
+
const FRONTEND_DIR = "frontend";
|
|
37
|
+
const APPS_WEB_DIR = "apps/web";
|
|
38
|
+
const BACKEND_DIR = "backend";
|
|
39
|
+
const SERVICES_DIR = "services";
|
|
40
|
+
const FRONTEND_LOCATIONS = [FRONTEND_DIR, APPS_WEB_DIR];
|
|
41
|
+
async function autoDetectServices(options) {
|
|
42
|
+
const { fs } = options;
|
|
43
|
+
const rootFrameworks = await (0, import_detect_framework.detectFrameworks)({
|
|
44
|
+
fs,
|
|
45
|
+
frameworkList: import_frameworks.default
|
|
46
|
+
});
|
|
47
|
+
if (rootFrameworks.length > 1) {
|
|
48
|
+
const frameworkNames = rootFrameworks.map((f) => f.name).join(", ");
|
|
49
|
+
return {
|
|
50
|
+
services: null,
|
|
51
|
+
errors: [
|
|
52
|
+
{
|
|
53
|
+
code: "MULTIPLE_FRAMEWORKS_ROOT",
|
|
54
|
+
message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit experimentalServices config.`
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (rootFrameworks.length === 1) {
|
|
60
|
+
return detectServicesAtRoot(fs, rootFrameworks[0]);
|
|
61
|
+
}
|
|
62
|
+
for (const frontendLocation of FRONTEND_LOCATIONS) {
|
|
63
|
+
const hasFrontendDir = await fs.hasPath(frontendLocation);
|
|
64
|
+
if (!hasFrontendDir) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const frontendFs = fs.chdir(frontendLocation);
|
|
68
|
+
const frontendFrameworks = await (0, import_detect_framework.detectFrameworks)({
|
|
69
|
+
fs: frontendFs,
|
|
70
|
+
frameworkList: import_frameworks.default
|
|
71
|
+
});
|
|
72
|
+
if (frontendFrameworks.length > 1) {
|
|
73
|
+
const frameworkNames = frontendFrameworks.map((f) => f.name).join(", ");
|
|
74
|
+
return {
|
|
75
|
+
services: null,
|
|
76
|
+
errors: [
|
|
77
|
+
{
|
|
78
|
+
code: "MULTIPLE_FRAMEWORKS_SERVICE",
|
|
79
|
+
message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit experimentalServices config.`
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (frontendFrameworks.length === 1) {
|
|
85
|
+
return detectServicesFrontendSubdir(
|
|
86
|
+
fs,
|
|
87
|
+
frontendFrameworks[0],
|
|
88
|
+
frontendLocation
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
services: null,
|
|
94
|
+
errors: [
|
|
95
|
+
{
|
|
96
|
+
code: "NO_SERVICES_CONFIGURED",
|
|
97
|
+
message: "No services detected. Configure experimentalServices in vercel.json or ensure a framework exists at project root, frontend/, or apps/web/."
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async function detectServicesAtRoot(fs, rootFramework) {
|
|
103
|
+
const services = {};
|
|
104
|
+
services.frontend = {
|
|
105
|
+
framework: rootFramework.slug ?? void 0,
|
|
106
|
+
routePrefix: "/"
|
|
107
|
+
};
|
|
108
|
+
const backendResult = await detectBackendServices(fs);
|
|
109
|
+
if (backendResult.error) {
|
|
110
|
+
return { services: null, errors: [backendResult.error] };
|
|
111
|
+
}
|
|
112
|
+
Object.assign(services, backendResult.services);
|
|
113
|
+
return { services, errors: [] };
|
|
114
|
+
}
|
|
115
|
+
async function detectServicesFrontendSubdir(fs, frontendFramework, frontendLocation) {
|
|
116
|
+
const services = {};
|
|
117
|
+
const serviceName = frontendLocation.split("/").pop() || "frontend";
|
|
118
|
+
services[serviceName] = {
|
|
119
|
+
framework: frontendFramework.slug ?? void 0,
|
|
120
|
+
workspace: frontendLocation,
|
|
121
|
+
routePrefix: "/"
|
|
122
|
+
};
|
|
123
|
+
const backendResult = await detectBackendServices(fs);
|
|
124
|
+
if (backendResult.error) {
|
|
125
|
+
return { services: null, errors: [backendResult.error] };
|
|
126
|
+
}
|
|
127
|
+
if (Object.keys(backendResult.services).length === 0) {
|
|
128
|
+
return {
|
|
129
|
+
services: null,
|
|
130
|
+
errors: [
|
|
131
|
+
{
|
|
132
|
+
code: "NO_BACKEND_SERVICES",
|
|
133
|
+
message: `Frontend detected in ${frontendLocation}/ but no backend services found. Add a backend/ or services/ directory with a supported framework.`
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
Object.assign(services, backendResult.services);
|
|
139
|
+
return { services, errors: [] };
|
|
140
|
+
}
|
|
141
|
+
async function detectBackendServices(fs) {
|
|
142
|
+
const services = {};
|
|
143
|
+
const backendResult = await detectServiceInDir(fs, BACKEND_DIR, "backend");
|
|
144
|
+
if (backendResult.error) {
|
|
145
|
+
return { services: {}, error: backendResult.error };
|
|
146
|
+
}
|
|
147
|
+
if (backendResult.service) {
|
|
148
|
+
services.backend = backendResult.service;
|
|
149
|
+
}
|
|
150
|
+
const multiServicesResult = await detectServicesDirectory(fs);
|
|
151
|
+
if (multiServicesResult.error) {
|
|
152
|
+
return { services: {}, error: multiServicesResult.error };
|
|
153
|
+
}
|
|
154
|
+
for (const serviceName of Object.keys(multiServicesResult.services)) {
|
|
155
|
+
if (services[serviceName]) {
|
|
156
|
+
return {
|
|
157
|
+
services: {},
|
|
158
|
+
error: {
|
|
159
|
+
code: "SERVICE_NAME_CONFLICT",
|
|
160
|
+
message: `Service name conflict: "${serviceName}" exists in both ${BACKEND_DIR}/ and ${SERVICES_DIR}/${serviceName}/. Rename one of the directories or use explicit experimentalServices config.`,
|
|
161
|
+
serviceName
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
Object.assign(services, multiServicesResult.services);
|
|
167
|
+
return { services };
|
|
168
|
+
}
|
|
169
|
+
async function detectServicesDirectory(fs) {
|
|
170
|
+
const services = {};
|
|
171
|
+
const hasServicesDir = await fs.hasPath(SERVICES_DIR);
|
|
172
|
+
if (!hasServicesDir) {
|
|
173
|
+
return { services };
|
|
174
|
+
}
|
|
175
|
+
const servicesFs = fs.chdir(SERVICES_DIR);
|
|
176
|
+
const entries = await servicesFs.readdir("/");
|
|
177
|
+
for (const entry of entries) {
|
|
178
|
+
if (entry.type !== "dir") {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const serviceName = entry.name;
|
|
182
|
+
const serviceDir = `${SERVICES_DIR}/${serviceName}`;
|
|
183
|
+
const result = await detectServiceInDir(fs, serviceDir, serviceName);
|
|
184
|
+
if (result.error) {
|
|
185
|
+
return { services: {}, error: result.error };
|
|
186
|
+
}
|
|
187
|
+
if (result.service) {
|
|
188
|
+
services[serviceName] = result.service;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return { services };
|
|
192
|
+
}
|
|
193
|
+
async function detectServiceInDir(fs, dirPath, serviceName) {
|
|
194
|
+
const hasDirPath = await fs.hasPath(dirPath);
|
|
195
|
+
if (!hasDirPath) {
|
|
196
|
+
return {};
|
|
197
|
+
}
|
|
198
|
+
const serviceFs = fs.chdir(dirPath);
|
|
199
|
+
const frameworks = await (0, import_detect_framework.detectFrameworks)({
|
|
200
|
+
fs: serviceFs,
|
|
201
|
+
frameworkList: import_frameworks.default
|
|
202
|
+
});
|
|
203
|
+
if (frameworks.length > 1) {
|
|
204
|
+
const frameworkNames = frameworks.map((f) => f.name).join(", ");
|
|
205
|
+
return {
|
|
206
|
+
error: {
|
|
207
|
+
code: "MULTIPLE_FRAMEWORKS_SERVICE",
|
|
208
|
+
message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit experimentalServices config.`,
|
|
209
|
+
serviceName
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
if (frameworks.length === 1) {
|
|
214
|
+
const framework = frameworks[0];
|
|
215
|
+
return {
|
|
216
|
+
service: {
|
|
217
|
+
framework: framework.slug ?? void 0,
|
|
218
|
+
workspace: dirPath,
|
|
219
|
+
routePrefix: `/_/${serviceName}`
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return {};
|
|
224
|
+
}
|
|
225
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
226
|
+
0 && (module.exports = {
|
|
227
|
+
autoDetectServices
|
|
228
|
+
});
|
|
@@ -9,11 +9,12 @@ export declare function detectServices(options: DetectServicesOptions): Promise<
|
|
|
9
9
|
/**
|
|
10
10
|
* Generate routing rules for services.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Routes are ordered by prefix length (longest first) to ensure more specific
|
|
13
|
+
* routes match before broader ones. For example, `/api/users` must be checked
|
|
14
|
+
* before `/api`, which must be checked before the catch-all `/`.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* - Static/SPA services: SPA fallback routes to index.html
|
|
17
|
+
* - Serverless services: Rewrite to the function entrypoint
|
|
18
|
+
* - Cron/Worker services: TODO - internal routes under `/_svc/`
|
|
18
19
|
*/
|
|
19
20
|
export declare function generateServicesRoutes(services: ResolvedService[]): ServicesRoutes;
|
|
@@ -24,6 +24,7 @@ __export(detect_services_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(detect_services_exports);
|
|
25
25
|
var import_utils = require("./utils");
|
|
26
26
|
var import_resolve = require("./resolve");
|
|
27
|
+
var import_auto_detect = require("./auto-detect");
|
|
27
28
|
async function detectServices(options) {
|
|
28
29
|
const { fs, workPath } = options;
|
|
29
30
|
const scopedFs = workPath ? fs.chdir(workPath) : fs;
|
|
@@ -39,6 +40,25 @@ async function detectServices(options) {
|
|
|
39
40
|
const configuredServices = vercelConfig?.experimentalServices;
|
|
40
41
|
const hasConfiguredServices = configuredServices && Object.keys(configuredServices).length > 0;
|
|
41
42
|
if (!hasConfiguredServices) {
|
|
43
|
+
const autoResult = await (0, import_auto_detect.autoDetectServices)({ fs: scopedFs });
|
|
44
|
+
if (autoResult.errors.length > 0) {
|
|
45
|
+
return {
|
|
46
|
+
services: [],
|
|
47
|
+
routes: { rewrites: [], defaults: [], crons: [], workers: [] },
|
|
48
|
+
errors: autoResult.errors,
|
|
49
|
+
warnings: []
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (autoResult.services) {
|
|
53
|
+
const result2 = (0, import_resolve.resolveAllConfiguredServices)(autoResult.services);
|
|
54
|
+
const routes2 = generateServicesRoutes(result2.services);
|
|
55
|
+
return {
|
|
56
|
+
services: result2.services,
|
|
57
|
+
routes: routes2,
|
|
58
|
+
errors: result2.errors,
|
|
59
|
+
warnings: []
|
|
60
|
+
};
|
|
61
|
+
}
|
|
42
62
|
return {
|
|
43
63
|
services: [],
|
|
44
64
|
routes: { rewrites: [], defaults: [], crons: [], workers: [] },
|
|
@@ -65,33 +85,34 @@ function generateServicesRoutes(services) {
|
|
|
65
85
|
const defaults = [];
|
|
66
86
|
const crons = [];
|
|
67
87
|
const workers = [];
|
|
68
|
-
const
|
|
88
|
+
const sortedWebServices = services.filter(
|
|
69
89
|
(s) => s.type === "web" && typeof s.routePrefix === "string"
|
|
70
|
-
);
|
|
71
|
-
const sortedWebServices = [...webServices].sort((a, b) => {
|
|
72
|
-
if (a.routePrefix === "/")
|
|
73
|
-
return 1;
|
|
74
|
-
if (b.routePrefix === "/")
|
|
75
|
-
return -1;
|
|
76
|
-
return b.routePrefix.length - a.routePrefix.length;
|
|
77
|
-
});
|
|
90
|
+
).sort((a, b) => b.routePrefix.length - a.routePrefix.length);
|
|
78
91
|
for (const service of sortedWebServices) {
|
|
79
|
-
const { routePrefix
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
src: "
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
const { routePrefix } = service;
|
|
93
|
+
const normalizedPrefix = routePrefix.slice(1);
|
|
94
|
+
if ((0, import_utils.isStaticBuild)(service)) {
|
|
95
|
+
if (routePrefix === "/") {
|
|
96
|
+
defaults.push({ handle: "filesystem" });
|
|
97
|
+
defaults.push({ src: "/(.*)", dest: "/index.html" });
|
|
98
|
+
} else {
|
|
99
|
+
rewrites.push({
|
|
100
|
+
src: `^/${normalizedPrefix}(?:/.*)?$`,
|
|
101
|
+
dest: `/${normalizedPrefix}/index.html`
|
|
102
|
+
});
|
|
103
|
+
}
|
|
88
104
|
} else {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
dest: functionPath,
|
|
93
|
-
|
|
94
|
-
|
|
105
|
+
const builderSrc = service.builder.src || routePrefix;
|
|
106
|
+
const functionPath = builderSrc.startsWith("/") ? builderSrc : `/${builderSrc}`;
|
|
107
|
+
if (routePrefix === "/") {
|
|
108
|
+
defaults.push({ src: "^/(.*)$", dest: functionPath, check: true });
|
|
109
|
+
} else {
|
|
110
|
+
rewrites.push({
|
|
111
|
+
src: `^/${normalizedPrefix}(?:/.*)?$`,
|
|
112
|
+
dest: functionPath,
|
|
113
|
+
check: true
|
|
114
|
+
});
|
|
115
|
+
}
|
|
95
116
|
}
|
|
96
117
|
}
|
|
97
118
|
return { rewrites, defaults, crons, workers };
|
package/dist/services/resolve.js
CHANGED
|
@@ -131,7 +131,7 @@ function resolveConfiguredService(name, config, group) {
|
|
|
131
131
|
builderUse = (0, import_utils.getBuilderForRuntime)(inferredRuntime);
|
|
132
132
|
builderSrc = config.entrypoint;
|
|
133
133
|
}
|
|
134
|
-
const routePrefix = type === "web" ? config.routePrefix : void 0;
|
|
134
|
+
const routePrefix = type === "web" && config.routePrefix ? config.routePrefix.startsWith("/") ? config.routePrefix : `/${config.routePrefix}` : void 0;
|
|
135
135
|
const isRoot = workspace === ".";
|
|
136
136
|
if (!isRoot && !builderSrc.startsWith(workspace + "/")) {
|
|
137
137
|
builderSrc = import_path.posix.join(workspace, builderSrc);
|
|
@@ -147,6 +147,13 @@ function resolveConfiguredService(name, config, group) {
|
|
|
147
147
|
builderConfig.excludeFiles = config.excludeFiles;
|
|
148
148
|
const isStaticBuild = import_types.STATIC_BUILDERS.has(builderUse);
|
|
149
149
|
const runtime = isStaticBuild ? void 0 : inferredRuntime;
|
|
150
|
+
if (routePrefix) {
|
|
151
|
+
const stripped = routePrefix.startsWith("/") ? routePrefix.slice(1) : routePrefix;
|
|
152
|
+
builderConfig.routePrefix = stripped || ".";
|
|
153
|
+
}
|
|
154
|
+
if (config.framework) {
|
|
155
|
+
builderConfig.framework = config.framework;
|
|
156
|
+
}
|
|
150
157
|
return {
|
|
151
158
|
name,
|
|
152
159
|
type,
|
package/dist/services/types.d.ts
CHANGED
|
@@ -1,29 +1,11 @@
|
|
|
1
1
|
import type { Route } from '@vercel/routing-utils';
|
|
2
|
-
import type { ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ServiceRuntime, ServiceType, Builder } from '@vercel/build-utils';
|
|
2
|
+
import type { ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ServiceRuntime, ServiceType, Service, Builder } from '@vercel/build-utils';
|
|
3
3
|
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
4
|
-
export type { ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ServiceRuntime, ServiceType, Builder, };
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
group?: string;
|
|
10
|
-
workspace: string;
|
|
11
|
-
entrypoint?: string;
|
|
12
|
-
framework?: string;
|
|
13
|
-
builder: Builder;
|
|
14
|
-
buildCommand?: string;
|
|
15
|
-
installCommand?: string;
|
|
16
|
-
runtime?: string;
|
|
17
|
-
/**
|
|
18
|
-
* URL path prefix for routing requests to this service.
|
|
19
|
-
* Required for web services; requests matching this prefix are routed to this service.
|
|
20
|
-
* Root services use "/" as the catch-all.
|
|
21
|
-
*/
|
|
22
|
-
routePrefix?: string;
|
|
23
|
-
schedule?: string;
|
|
24
|
-
topic?: string;
|
|
25
|
-
consumer?: string;
|
|
26
|
-
}
|
|
4
|
+
export type { ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ServiceRuntime, ServiceType, Service, Builder, };
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated Use `Service` instead
|
|
7
|
+
*/
|
|
8
|
+
export type ResolvedService = Service;
|
|
27
9
|
export interface DetectServicesOptions {
|
|
28
10
|
fs: DetectorFilesystem;
|
|
29
11
|
/**
|
package/dist/services/utils.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
2
|
-
import type { ServiceRuntime, ExperimentalServices, ServiceDetectionError } from './types';
|
|
2
|
+
import type { ServiceRuntime, ExperimentalServices, ServiceDetectionError, ResolvedService } from './types';
|
|
3
3
|
export declare function getBuilderForRuntime(runtime: ServiceRuntime): string;
|
|
4
|
+
export declare function isStaticBuild(service: ResolvedService): boolean;
|
|
4
5
|
/**
|
|
5
6
|
* Infer runtime from available service configuration.
|
|
6
7
|
*
|
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
|
+
isStaticBuild: () => isStaticBuild,
|
|
23
24
|
readVercelConfig: () => readVercelConfig
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(utils_exports);
|
|
@@ -32,6 +33,9 @@ function getBuilderForRuntime(runtime) {
|
|
|
32
33
|
}
|
|
33
34
|
return builder;
|
|
34
35
|
}
|
|
36
|
+
function isStaticBuild(service) {
|
|
37
|
+
return import_types.STATIC_BUILDERS.has(service.builder.use);
|
|
38
|
+
}
|
|
35
39
|
function inferServiceRuntime(config) {
|
|
36
40
|
if (config.runtime && config.runtime in import_types.RUNTIME_BUILDERS) {
|
|
37
41
|
return config.runtime;
|
|
@@ -81,5 +85,6 @@ async function readVercelConfig(fs) {
|
|
|
81
85
|
0 && (module.exports = {
|
|
82
86
|
getBuilderForRuntime,
|
|
83
87
|
inferServiceRuntime,
|
|
88
|
+
isStaticBuild,
|
|
84
89
|
readVercelConfig
|
|
85
90
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/fs-detectors",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.8.0",
|
|
4
4
|
"description": "Vercel filesystem detectors",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -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.
|
|
35
|
+
"@vercel/build-utils": "13.3.0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "node ../../utils/build.mjs",
|