@vercel/fs-detectors 5.8.6 → 5.8.7
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/detect-services.js +8 -2
- package/dist/services/resolve.d.ts +6 -5
- package/dist/services/resolve.js +81 -9
- package/dist/services/types.d.ts +2 -1
- package/dist/services/types.js +16 -0
- package/dist/services/utils.d.ts +1 -0
- package/dist/services/utils.js +9 -0
- package/package.json +3 -3
|
@@ -51,7 +51,10 @@ async function detectServices(options) {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
if (autoResult.services) {
|
|
54
|
-
const result2 = (0, import_resolve.resolveAllConfiguredServices)(
|
|
54
|
+
const result2 = await (0, import_resolve.resolveAllConfiguredServices)(
|
|
55
|
+
autoResult.services,
|
|
56
|
+
scopedFs
|
|
57
|
+
);
|
|
55
58
|
const routes2 = generateServicesRoutes(result2.services);
|
|
56
59
|
return {
|
|
57
60
|
services: result2.services,
|
|
@@ -72,7 +75,10 @@ async function detectServices(options) {
|
|
|
72
75
|
warnings: []
|
|
73
76
|
};
|
|
74
77
|
}
|
|
75
|
-
const result = (0, import_resolve.resolveAllConfiguredServices)(
|
|
78
|
+
const result = await (0, import_resolve.resolveAllConfiguredServices)(
|
|
79
|
+
configuredServices,
|
|
80
|
+
scopedFs
|
|
81
|
+
);
|
|
76
82
|
const routes = generateServicesRoutes(result.services);
|
|
77
83
|
return {
|
|
78
84
|
services: result.services,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Service, ExperimentalServiceConfig, ExperimentalServices, ServiceDetectionError } from './types';
|
|
2
|
+
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
2
3
|
/**
|
|
3
4
|
* Validate a service configuration from vercel.json experimentalServices.
|
|
4
5
|
*/
|
|
@@ -6,12 +7,12 @@ export declare function validateServiceConfig(name: string, config: Experimental
|
|
|
6
7
|
/**
|
|
7
8
|
* Resolve a single service from user configuration.
|
|
8
9
|
*/
|
|
9
|
-
export declare function resolveConfiguredService(name: string, config: ExperimentalServiceConfig, group?: string):
|
|
10
|
+
export declare function resolveConfiguredService(name: string, config: ExperimentalServiceConfig, fs: DetectorFilesystem, group?: string): Promise<Service>;
|
|
10
11
|
/**
|
|
11
12
|
* Resolve all services from vercel.json experimentalServices.
|
|
12
13
|
* Validates each service configuration.
|
|
13
14
|
*/
|
|
14
|
-
export declare function resolveAllConfiguredServices(services: ExperimentalServices): {
|
|
15
|
-
services:
|
|
15
|
+
export declare function resolveAllConfiguredServices(services: ExperimentalServices, fs: DetectorFilesystem): Promise<{
|
|
16
|
+
services: Service[];
|
|
16
17
|
errors: ServiceDetectionError[];
|
|
17
|
-
}
|
|
18
|
+
}>;
|
package/dist/services/resolve.js
CHANGED
|
@@ -40,6 +40,61 @@ var import_frameworks = __toESM(require("@vercel/frameworks"));
|
|
|
40
40
|
var import_routing_utils = require("@vercel/routing-utils");
|
|
41
41
|
const frameworksBySlug = new Map(import_frameworks.default.map((f) => [f.slug, f]));
|
|
42
42
|
const SERVICE_NAME_REGEX = /^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
|
|
43
|
+
function toWorkspaceRelativeEntrypoint(entrypoint, workspace) {
|
|
44
|
+
const normalizedEntrypoint = import_path.posix.normalize(entrypoint);
|
|
45
|
+
if (workspace === ".") {
|
|
46
|
+
return normalizedEntrypoint;
|
|
47
|
+
}
|
|
48
|
+
const workspacePrefix = `${workspace}/`;
|
|
49
|
+
if (normalizedEntrypoint.startsWith(workspacePrefix)) {
|
|
50
|
+
return normalizedEntrypoint.slice(workspacePrefix.length);
|
|
51
|
+
}
|
|
52
|
+
const relativeEntrypoint = import_path.posix.relative(
|
|
53
|
+
workspace,
|
|
54
|
+
normalizedEntrypoint
|
|
55
|
+
);
|
|
56
|
+
if (relativeEntrypoint === "" || relativeEntrypoint.startsWith("..")) {
|
|
57
|
+
return normalizedEntrypoint;
|
|
58
|
+
}
|
|
59
|
+
return relativeEntrypoint;
|
|
60
|
+
}
|
|
61
|
+
async function inferWorkspaceFromNearestManifest({
|
|
62
|
+
fs,
|
|
63
|
+
entrypoint,
|
|
64
|
+
runtime
|
|
65
|
+
}) {
|
|
66
|
+
if (!entrypoint || !runtime) {
|
|
67
|
+
return void 0;
|
|
68
|
+
}
|
|
69
|
+
const manifests = import_types.RUNTIME_MANIFESTS[runtime];
|
|
70
|
+
if (!manifests || manifests.length === 0) {
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
let dir = import_path.posix.dirname(import_path.posix.normalize(entrypoint)) || ".";
|
|
74
|
+
if (dir === "") {
|
|
75
|
+
dir = ".";
|
|
76
|
+
}
|
|
77
|
+
let reachedRoot = false;
|
|
78
|
+
while (!reachedRoot) {
|
|
79
|
+
for (const manifest of manifests) {
|
|
80
|
+
const manifestPath = dir === "." ? manifest : import_path.posix.join(dir, manifest);
|
|
81
|
+
if (await (0, import_utils.hasFile)(fs, manifestPath)) {
|
|
82
|
+
return dir;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (dir === "." || dir === "/") {
|
|
86
|
+
reachedRoot = true;
|
|
87
|
+
} else {
|
|
88
|
+
const parent = import_path.posix.dirname(dir);
|
|
89
|
+
if (!parent || parent === dir) {
|
|
90
|
+
reachedRoot = true;
|
|
91
|
+
} else {
|
|
92
|
+
dir = parent;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return void 0;
|
|
97
|
+
}
|
|
43
98
|
function isReservedServiceRoutePrefix(routePrefix) {
|
|
44
99
|
const normalized = (0, import_routing_utils.normalizeRoutePrefix)(routePrefix);
|
|
45
100
|
return normalized === import_utils.INTERNAL_SERVICE_PREFIX || normalized.startsWith(`${import_utils.INTERNAL_SERVICE_PREFIX}/`);
|
|
@@ -132,24 +187,41 @@ function validateServiceConfig(name, config) {
|
|
|
132
187
|
}
|
|
133
188
|
return null;
|
|
134
189
|
}
|
|
135
|
-
function resolveConfiguredService(name, config, group) {
|
|
190
|
+
async function resolveConfiguredService(name, config, fs, group) {
|
|
136
191
|
const type = config.type || "web";
|
|
137
|
-
const
|
|
192
|
+
const inferredRuntime = (0, import_utils.inferServiceRuntime)(config);
|
|
193
|
+
let workspace = config.workspace || ".";
|
|
194
|
+
let resolvedEntrypoint = config.entrypoint;
|
|
195
|
+
if (!config.workspace) {
|
|
196
|
+
const inferredWorkspace = await inferWorkspaceFromNearestManifest({
|
|
197
|
+
fs,
|
|
198
|
+
entrypoint: resolvedEntrypoint,
|
|
199
|
+
runtime: inferredRuntime
|
|
200
|
+
});
|
|
201
|
+
if (inferredWorkspace) {
|
|
202
|
+
workspace = inferredWorkspace;
|
|
203
|
+
if (resolvedEntrypoint) {
|
|
204
|
+
resolvedEntrypoint = toWorkspaceRelativeEntrypoint(
|
|
205
|
+
resolvedEntrypoint,
|
|
206
|
+
inferredWorkspace
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
138
211
|
const topic = type === "worker" ? config.topic || "default" : config.topic;
|
|
139
212
|
const consumer = type === "worker" ? config.consumer || "default" : config.consumer;
|
|
140
|
-
const inferredRuntime = (0, import_utils.inferServiceRuntime)(config);
|
|
141
213
|
let builderUse;
|
|
142
214
|
let builderSrc;
|
|
143
215
|
if (config.framework) {
|
|
144
216
|
const framework = frameworksBySlug.get(config.framework);
|
|
145
217
|
builderUse = framework?.useRuntime?.use || "@vercel/static-build";
|
|
146
|
-
builderSrc =
|
|
218
|
+
builderSrc = resolvedEntrypoint || framework?.useRuntime?.src || "package.json";
|
|
147
219
|
} else if (config.builder) {
|
|
148
220
|
builderUse = config.builder;
|
|
149
|
-
builderSrc =
|
|
221
|
+
builderSrc = resolvedEntrypoint;
|
|
150
222
|
} else {
|
|
151
223
|
builderUse = (0, import_utils.getBuilderForRuntime)(inferredRuntime);
|
|
152
|
-
builderSrc =
|
|
224
|
+
builderSrc = resolvedEntrypoint;
|
|
153
225
|
}
|
|
154
226
|
const routePrefix = type === "web" && config.routePrefix ? config.routePrefix.startsWith("/") ? config.routePrefix : `/${config.routePrefix}` : void 0;
|
|
155
227
|
const isRoot = workspace === ".";
|
|
@@ -182,7 +254,7 @@ function resolveConfiguredService(name, config, group) {
|
|
|
182
254
|
type,
|
|
183
255
|
group,
|
|
184
256
|
workspace,
|
|
185
|
-
entrypoint:
|
|
257
|
+
entrypoint: resolvedEntrypoint,
|
|
186
258
|
routePrefix,
|
|
187
259
|
framework: config.framework,
|
|
188
260
|
builder: {
|
|
@@ -198,7 +270,7 @@ function resolveConfiguredService(name, config, group) {
|
|
|
198
270
|
consumer
|
|
199
271
|
};
|
|
200
272
|
}
|
|
201
|
-
function resolveAllConfiguredServices(services) {
|
|
273
|
+
async function resolveAllConfiguredServices(services, fs) {
|
|
202
274
|
const resolved = [];
|
|
203
275
|
const errors = [];
|
|
204
276
|
const webServicesByRoutePrefix = /* @__PURE__ */ new Map();
|
|
@@ -209,7 +281,7 @@ function resolveAllConfiguredServices(services) {
|
|
|
209
281
|
errors.push(validationError);
|
|
210
282
|
continue;
|
|
211
283
|
}
|
|
212
|
-
const service = resolveConfiguredService(name, serviceConfig);
|
|
284
|
+
const service = await resolveConfiguredService(name, serviceConfig, fs);
|
|
213
285
|
if (service.type === "web" && typeof service.routePrefix === "string") {
|
|
214
286
|
const normalizedRoutePrefix = (0, import_routing_utils.normalizeRoutePrefix)(service.routePrefix);
|
|
215
287
|
const existingServiceName = webServicesByRoutePrefix.get(
|
package/dist/services/types.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export interface ServicesRoutes {
|
|
|
33
33
|
workers: Route[];
|
|
34
34
|
}
|
|
35
35
|
export interface DetectServicesResult {
|
|
36
|
-
services:
|
|
36
|
+
services: Service[];
|
|
37
37
|
/** Routing rules derived from services */
|
|
38
38
|
routes: ServicesRoutes;
|
|
39
39
|
errors: ServiceDetectionError[];
|
|
@@ -50,6 +50,7 @@ export interface ServiceDetectionError {
|
|
|
50
50
|
serviceName?: string;
|
|
51
51
|
}
|
|
52
52
|
export declare const RUNTIME_BUILDERS: Record<ServiceRuntime, string>;
|
|
53
|
+
export declare const RUNTIME_MANIFESTS: Partial<Record<ServiceRuntime, string[]>>;
|
|
53
54
|
export declare const ENTRYPOINT_EXTENSIONS: Record<string, ServiceRuntime>;
|
|
54
55
|
/**
|
|
55
56
|
* Builders that produce static output (SPAs, static sites).
|
package/dist/services/types.js
CHANGED
|
@@ -21,6 +21,7 @@ __export(types_exports, {
|
|
|
21
21
|
ENTRYPOINT_EXTENSIONS: () => ENTRYPOINT_EXTENSIONS,
|
|
22
22
|
ROUTE_OWNING_BUILDERS: () => ROUTE_OWNING_BUILDERS,
|
|
23
23
|
RUNTIME_BUILDERS: () => RUNTIME_BUILDERS,
|
|
24
|
+
RUNTIME_MANIFESTS: () => RUNTIME_MANIFESTS,
|
|
24
25
|
STATIC_BUILDERS: () => STATIC_BUILDERS
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(types_exports);
|
|
@@ -31,6 +32,20 @@ const RUNTIME_BUILDERS = {
|
|
|
31
32
|
rust: "@vercel/rust",
|
|
32
33
|
ruby: "@vercel/ruby"
|
|
33
34
|
};
|
|
35
|
+
const RUNTIME_MANIFESTS = {
|
|
36
|
+
node: ["package.json"],
|
|
37
|
+
python: [
|
|
38
|
+
"pyproject.toml",
|
|
39
|
+
"requirements.txt",
|
|
40
|
+
"Pipfile",
|
|
41
|
+
"pylock.yml",
|
|
42
|
+
"uv.lock",
|
|
43
|
+
"setup.py"
|
|
44
|
+
],
|
|
45
|
+
go: ["go.mod"],
|
|
46
|
+
ruby: ["Gemfile"],
|
|
47
|
+
rust: ["Cargo.toml"]
|
|
48
|
+
};
|
|
34
49
|
const ENTRYPOINT_EXTENSIONS = {
|
|
35
50
|
".ts": "node",
|
|
36
51
|
".mts": "node",
|
|
@@ -56,5 +71,6 @@ const ROUTE_OWNING_BUILDERS = /* @__PURE__ */ new Set([
|
|
|
56
71
|
ENTRYPOINT_EXTENSIONS,
|
|
57
72
|
ROUTE_OWNING_BUILDERS,
|
|
58
73
|
RUNTIME_BUILDERS,
|
|
74
|
+
RUNTIME_MANIFESTS,
|
|
59
75
|
STATIC_BUILDERS
|
|
60
76
|
});
|
package/dist/services/utils.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
2
2
|
import type { ServiceRuntime, ExperimentalServices, ServiceDetectionError, ResolvedService } from './types';
|
|
3
|
+
export declare function hasFile(fs: DetectorFilesystem, filePath: string): Promise<boolean>;
|
|
3
4
|
/**
|
|
4
5
|
* Reserved internal namespace used by services routing/runtime plumbing.
|
|
5
6
|
*/
|
package/dist/services/utils.js
CHANGED
|
@@ -21,6 +21,7 @@ __export(utils_exports, {
|
|
|
21
21
|
INTERNAL_SERVICE_PREFIX: () => INTERNAL_SERVICE_PREFIX,
|
|
22
22
|
getBuilderForRuntime: () => getBuilderForRuntime,
|
|
23
23
|
getInternalServiceFunctionPath: () => getInternalServiceFunctionPath,
|
|
24
|
+
hasFile: () => hasFile,
|
|
24
25
|
inferServiceRuntime: () => inferServiceRuntime,
|
|
25
26
|
isRouteOwningBuilder: () => isRouteOwningBuilder,
|
|
26
27
|
isStaticBuild: () => isStaticBuild,
|
|
@@ -29,6 +30,13 @@ __export(utils_exports, {
|
|
|
29
30
|
module.exports = __toCommonJS(utils_exports);
|
|
30
31
|
var import_framework_helpers = require("@vercel/build-utils/dist/framework-helpers");
|
|
31
32
|
var import_types = require("./types");
|
|
33
|
+
async function hasFile(fs, filePath) {
|
|
34
|
+
try {
|
|
35
|
+
return await fs.isFile(filePath);
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
32
40
|
const INTERNAL_SERVICE_PREFIX = "/_svc";
|
|
33
41
|
function getInternalServiceFunctionPath(serviceName) {
|
|
34
42
|
return `${INTERNAL_SERVICE_PREFIX}/${serviceName}/index`;
|
|
@@ -96,6 +104,7 @@ async function readVercelConfig(fs) {
|
|
|
96
104
|
INTERNAL_SERVICE_PREFIX,
|
|
97
105
|
getBuilderForRuntime,
|
|
98
106
|
getInternalServiceFunctionPath,
|
|
107
|
+
hasFile,
|
|
99
108
|
inferServiceRuntime,
|
|
100
109
|
isRouteOwningBuilder,
|
|
101
110
|
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.7",
|
|
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/error-utils": "2.0.3",
|
|
23
23
|
"@vercel/frameworks": "3.17.1",
|
|
24
|
-
"@vercel/
|
|
24
|
+
"@vercel/routing-utils": "5.3.3"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/glob": "7.2.0",
|