@vercel/fs-detectors 5.15.1 → 5.15.2
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 +104 -13
- package/package.json +4 -4
package/dist/services/resolve.js
CHANGED
|
@@ -160,6 +160,84 @@ function isReservedServiceRoutePrefix(routePrefix) {
|
|
|
160
160
|
const normalized = (0, import_routing_utils.normalizeRoutePrefix)(routePrefix);
|
|
161
161
|
return normalized === import_utils.INTERNAL_SERVICE_PREFIX || normalized.startsWith(`${import_utils.INTERNAL_SERVICE_PREFIX}/`);
|
|
162
162
|
}
|
|
163
|
+
function resolveServiceRoutingConfig(name, config) {
|
|
164
|
+
const hasLegacyRoutePrefix = typeof config.routePrefix === "string";
|
|
165
|
+
const hasLegacySubdomain = typeof config.subdomain === "string";
|
|
166
|
+
if (config.mount === void 0) {
|
|
167
|
+
return {
|
|
168
|
+
routing: {
|
|
169
|
+
routePrefix: config.routePrefix,
|
|
170
|
+
subdomain: config.subdomain,
|
|
171
|
+
routePrefixConfigured: hasLegacyRoutePrefix
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (hasLegacyRoutePrefix || hasLegacySubdomain) {
|
|
176
|
+
return {
|
|
177
|
+
error: {
|
|
178
|
+
code: "CONFLICTING_MOUNT_CONFIG",
|
|
179
|
+
message: `Service "${name}" cannot mix "mount" with "routePrefix" or "subdomain". Use only one routing configuration style.`,
|
|
180
|
+
serviceName: name
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (typeof config.mount === "string") {
|
|
185
|
+
return {
|
|
186
|
+
routing: {
|
|
187
|
+
routePrefix: config.mount,
|
|
188
|
+
routePrefixConfigured: true
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (!config.mount || typeof config.mount !== "object" || Array.isArray(config.mount)) {
|
|
193
|
+
return {
|
|
194
|
+
error: {
|
|
195
|
+
code: "INVALID_MOUNT",
|
|
196
|
+
message: `Service "${name}" has invalid "mount" config. Use a string path such as "/api" or an object like { path: "/api", subdomain: "api" }.`,
|
|
197
|
+
serviceName: name
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const hasInvalidMountKeys = Object.keys(config.mount).some(
|
|
202
|
+
(key) => key !== "path" && key !== "subdomain"
|
|
203
|
+
);
|
|
204
|
+
if (hasInvalidMountKeys) {
|
|
205
|
+
return {
|
|
206
|
+
error: {
|
|
207
|
+
code: "INVALID_MOUNT",
|
|
208
|
+
message: `Service "${name}" has invalid "mount" config. Only "path" and "subdomain" are supported.`,
|
|
209
|
+
serviceName: name
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const mountPath = config.mount.path;
|
|
214
|
+
const mountSubdomain = config.mount.subdomain;
|
|
215
|
+
if (mountPath !== void 0 && typeof mountPath !== "string" || mountSubdomain !== void 0 && typeof mountSubdomain !== "string") {
|
|
216
|
+
return {
|
|
217
|
+
error: {
|
|
218
|
+
code: "INVALID_MOUNT",
|
|
219
|
+
message: `Service "${name}" has invalid "mount" config. "path" and "subdomain" must be strings when provided.`,
|
|
220
|
+
serviceName: name
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
if (typeof mountPath !== "string" && typeof mountSubdomain !== "string") {
|
|
225
|
+
return {
|
|
226
|
+
error: {
|
|
227
|
+
code: "INVALID_MOUNT",
|
|
228
|
+
message: `Service "${name}" has invalid "mount" config. Specify at least one of "mount.path" or "mount.subdomain".`,
|
|
229
|
+
serviceName: name
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
routing: {
|
|
235
|
+
routePrefix: mountPath,
|
|
236
|
+
subdomain: mountSubdomain,
|
|
237
|
+
routePrefixConfigured: typeof mountPath === "string"
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
163
241
|
function validateServiceConfig(name, config) {
|
|
164
242
|
if (!SERVICE_NAME_REGEX.test(name)) {
|
|
165
243
|
return {
|
|
@@ -176,40 +254,46 @@ function validateServiceConfig(name, config) {
|
|
|
176
254
|
};
|
|
177
255
|
}
|
|
178
256
|
const serviceType = config.type || "web";
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
257
|
+
const routingResult = resolveServiceRoutingConfig(name, config);
|
|
258
|
+
if (routingResult.error) {
|
|
259
|
+
return routingResult.error;
|
|
260
|
+
}
|
|
261
|
+
const configuredRoutePrefix = routingResult.routing?.routePrefix;
|
|
262
|
+
const configuredSubdomain = routingResult.routing?.subdomain;
|
|
263
|
+
const hasRoutePrefix = typeof configuredRoutePrefix === "string";
|
|
264
|
+
const hasSubdomain = typeof configuredSubdomain === "string";
|
|
265
|
+
if (hasSubdomain && !DNS_LABEL_RE.test(configuredSubdomain)) {
|
|
182
266
|
return {
|
|
183
267
|
code: "INVALID_SUBDOMAIN",
|
|
184
|
-
message: `Web service "${name}" has invalid subdomain "${
|
|
268
|
+
message: `Web service "${name}" has invalid subdomain "${configuredSubdomain}". Use a single DNS label such as "api".`,
|
|
185
269
|
serviceName: name
|
|
186
270
|
};
|
|
187
271
|
}
|
|
188
272
|
if (serviceType === "web" && !hasRoutePrefix && !hasSubdomain) {
|
|
189
273
|
return {
|
|
190
274
|
code: "MISSING_ROUTE_PREFIX",
|
|
191
|
-
message: `Web service "${name}" must specify at least one of "routePrefix" or "subdomain".`,
|
|
275
|
+
message: `Web service "${name}" must specify at least one of "mount", "routePrefix", or "subdomain".`,
|
|
192
276
|
serviceName: name
|
|
193
277
|
};
|
|
194
278
|
}
|
|
195
|
-
if (serviceType === "web" &&
|
|
279
|
+
if (serviceType === "web" && configuredRoutePrefix && isReservedServiceRoutePrefix(configuredRoutePrefix)) {
|
|
196
280
|
return {
|
|
197
281
|
code: "RESERVED_ROUTE_PREFIX",
|
|
198
|
-
message: `Web service "${name}" cannot use routePrefix "${
|
|
282
|
+
message: `Web service "${name}" cannot use routePrefix "${configuredRoutePrefix}". The "${import_utils.INTERNAL_SERVICE_PREFIX}" prefix is reserved for internal services routing.`,
|
|
199
283
|
serviceName: name
|
|
200
284
|
};
|
|
201
285
|
}
|
|
202
|
-
if ((serviceType === "worker" || serviceType === "cron") &&
|
|
286
|
+
if ((serviceType === "worker" || serviceType === "cron") && configuredRoutePrefix) {
|
|
203
287
|
return {
|
|
204
288
|
code: "INVALID_ROUTE_PREFIX",
|
|
205
|
-
message: `${serviceType === "worker" ? "Worker" : "Cron"} service "${name}" cannot have "routePrefix". Only web services should specify
|
|
289
|
+
message: `${serviceType === "worker" ? "Worker" : "Cron"} service "${name}" cannot have "routePrefix" or "mount". Only web services should specify path-based routing.`,
|
|
206
290
|
serviceName: name
|
|
207
291
|
};
|
|
208
292
|
}
|
|
209
293
|
if ((serviceType === "worker" || serviceType === "cron") && hasSubdomain) {
|
|
210
294
|
return {
|
|
211
295
|
code: "INVALID_HOST_ROUTING_CONFIG",
|
|
212
|
-
message: `${serviceType === "worker" ? "Worker" : "Cron"} service "${name}" cannot have "subdomain". Only web services should specify subdomain routing.`,
|
|
296
|
+
message: `${serviceType === "worker" ? "Worker" : "Cron"} service "${name}" cannot have "subdomain" or "mount.subdomain". Only web services should specify subdomain routing.`,
|
|
213
297
|
serviceName: name
|
|
214
298
|
};
|
|
215
299
|
}
|
|
@@ -301,6 +385,13 @@ async function resolveConfiguredService(options) {
|
|
|
301
385
|
const type = config.type || "web";
|
|
302
386
|
const rawEntrypoint = config.entrypoint;
|
|
303
387
|
const moduleAttrParsed = typeof rawEntrypoint === "string" && type === "cron" ? parsePyModuleAttrEntrypoint(rawEntrypoint) : null;
|
|
388
|
+
const routingResult = resolveServiceRoutingConfig(name, config);
|
|
389
|
+
if (routingResult.error) {
|
|
390
|
+
throw new Error(routingResult.error.message);
|
|
391
|
+
}
|
|
392
|
+
const configuredRoutePrefix = routingResult.routing?.routePrefix;
|
|
393
|
+
const configuredSubdomain = routingResult.routing?.subdomain;
|
|
394
|
+
const routePrefixWasConfigured = routingResult.routing?.routePrefixConfigured ?? false;
|
|
304
395
|
let resolvedEntrypointPath = resolvedEntrypoint;
|
|
305
396
|
if (!resolvedEntrypointPath && typeof rawEntrypoint === "string") {
|
|
306
397
|
const entrypointToResolve = moduleAttrParsed ? moduleAttrParsed.filePath : rawEntrypoint;
|
|
@@ -370,10 +461,10 @@ async function resolveConfiguredService(options) {
|
|
|
370
461
|
}
|
|
371
462
|
builderSrc = resolvedEntrypointFile;
|
|
372
463
|
}
|
|
373
|
-
const normalizedSubdomain = type === "web" && typeof
|
|
464
|
+
const normalizedSubdomain = type === "web" && typeof configuredSubdomain === "string" ? configuredSubdomain.toLowerCase() : void 0;
|
|
374
465
|
const defaultRoutePrefix = type === "web" && normalizedSubdomain ? `/_/${name}` : void 0;
|
|
375
|
-
const routePrefix = type === "web" && (
|
|
376
|
-
const resolvedRoutePrefixSource = type === "web" && typeof routePrefix === "string" ?
|
|
466
|
+
const routePrefix = type === "web" && (configuredRoutePrefix || defaultRoutePrefix) ? (configuredRoutePrefix || defaultRoutePrefix).startsWith("/") ? configuredRoutePrefix || defaultRoutePrefix : `/${configuredRoutePrefix || defaultRoutePrefix}` : void 0;
|
|
467
|
+
const resolvedRoutePrefixSource = type === "web" && typeof routePrefix === "string" ? routePrefixWasConfigured ? routePrefixSource : "generated" : void 0;
|
|
377
468
|
const isRoot = workspace === ".";
|
|
378
469
|
if (!isRoot) {
|
|
379
470
|
builderSrc = import_path.posix.join(workspace, builderSrc);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/fs-detectors",
|
|
3
|
-
"version": "5.15.
|
|
3
|
+
"version": "5.15.2",
|
|
4
4
|
"description": "Vercel filesystem detectors",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"minimatch": "3.1.2",
|
|
21
21
|
"semver": "6.3.1",
|
|
22
22
|
"smol-toml": "1.5.2",
|
|
23
|
-
"@vercel/build-utils": "13.14.1",
|
|
24
|
-
"@vercel/error-utils": "2.0.3",
|
|
25
23
|
"@vercel/frameworks": "3.24.0",
|
|
26
|
-
"@vercel/
|
|
24
|
+
"@vercel/build-utils": "13.14.2",
|
|
25
|
+
"@vercel/routing-utils": "6.1.1",
|
|
26
|
+
"@vercel/error-utils": "2.0.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/glob": "7.2.0",
|