@vercel/fs-detectors 6.7.6 → 6.7.8
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/detect-builders.js +7 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +12 -0
- package/dist/services/detect-services.d.ts +1 -1
- package/dist/services/detect-services.js +22 -2
- package/dist/services/get-services-builders.d.ts +3 -3
- package/dist/services/resolve-v2.d.ts +11 -0
- package/dist/services/resolve-v2.js +264 -0
- package/dist/services/resolve.d.ts +33 -3
- package/dist/services/resolve.js +11 -0
- package/dist/services/types.d.ts +6 -5
- package/dist/services/utils.d.ts +2 -1
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Route } from '@vercel/routing-utils';
|
|
2
|
-
import type { PackageJson, Builder, BuilderFunctions, ExperimentalServices, ProjectSettings, Service } from '@vercel/build-utils';
|
|
2
|
+
import type { PackageJson, Builder, BuilderFunctions, ExperimentalServices, ProjectSettings, Service, ExperimentalServicesV2 } from '@vercel/build-utils';
|
|
3
3
|
/**
|
|
4
4
|
* Pattern for finding all supported middleware files.
|
|
5
5
|
*/
|
|
@@ -23,6 +23,7 @@ export interface Options {
|
|
|
23
23
|
tag?: string;
|
|
24
24
|
functions?: BuilderFunctions;
|
|
25
25
|
experimentalServices?: ExperimentalServices;
|
|
26
|
+
experimentalServicesV2?: ExperimentalServicesV2;
|
|
26
27
|
ignoreBuildScript?: boolean;
|
|
27
28
|
projectSettings?: ProjectSettings;
|
|
28
29
|
cleanUrls?: boolean;
|
package/dist/detect-builders.js
CHANGED
|
@@ -92,10 +92,14 @@ function detectOutputDirectory(builders) {
|
|
|
92
92
|
return publicBuilder ? publicBuilder.src.replace("/**/*", "") : null;
|
|
93
93
|
}
|
|
94
94
|
async function detectBuilders(files, pkg, options = {}) {
|
|
95
|
-
const {
|
|
95
|
+
const {
|
|
96
|
+
experimentalServices,
|
|
97
|
+
experimentalServicesV2,
|
|
98
|
+
projectSettings = {}
|
|
99
|
+
} = options;
|
|
96
100
|
const { framework } = projectSettings;
|
|
97
|
-
const configuredServices = experimentalServices;
|
|
98
|
-
const configuredServicesType = "experimentalServices";
|
|
101
|
+
const configuredServices = experimentalServices ?? experimentalServicesV2;
|
|
102
|
+
const configuredServicesType = experimentalServices ? "experimentalServices" : "experimentalServicesV2";
|
|
99
103
|
const hasServicesConfig = configuredServices != null && typeof configuredServices === "object";
|
|
100
104
|
if (hasServicesConfig || framework === "services") {
|
|
101
105
|
return (0, import_get_services_builders.getServicesBuilders)({
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
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 { resolveAllConfiguredServicesV2, resolveConfiguredServiceV2, validateServiceConfigV2, } from './services/resolve-v2';
|
|
4
|
+
export { isExperimentalService, isExperimentalServiceV2, } from '@vercel/build-utils';
|
|
3
5
|
export { autoDetectServices } from './services/auto-detect';
|
|
4
6
|
export type { AutoDetectOptions, AutoDetectResult, } from './services/auto-detect';
|
|
5
7
|
export { isStaticBuild, isRouteOwningBuilder, INTERNAL_SERVICE_PREFIX, getInternalServiceFunctionPath, getInternalServiceCronPath, getInternalServiceCronPathPrefix, getInternalServiceWorkerPath, getInternalServiceWorkerPathPrefix, } from './services/utils';
|
|
6
8
|
export { getServicesBuilders } from './services/get-services-builders';
|
|
7
|
-
export type { DetectServicesOptions, DetectServicesResult, DetectServicesSource, InferredServicesConfig, ResolvedServicesResult, InferredServicesResult, ResolvedService, Service, ServicesRoutes, ServiceDetectionError, } from './services/types';
|
|
9
|
+
export type { DetectServicesOptions, DetectServicesResult, DetectServicesSource, InferredServicesConfig, ResolvedServicesResult, InferredServicesResult, ResolvedService, Service, ExperimentalService, ExperimentalServiceV2, ExperimentalServiceV2Config, ExperimentalServicesV2, ExperimentalServiceV2Binding, ServicesRoutes, ServiceDetectionError, } from './services/types';
|
|
8
10
|
export { detectFileSystemAPI } from './detect-file-system-api';
|
|
9
11
|
export { detectFramework, detectFrameworks, detectFrameworkRecord, detectFrameworkVersion, } from './detect-framework';
|
|
10
12
|
export { getProjectPaths } from './get-project-paths';
|
package/dist/index.js
CHANGED
|
@@ -49,17 +49,24 @@ __export(src_exports, {
|
|
|
49
49
|
getServicesBuilders: () => import_get_services_builders.getServicesBuilders,
|
|
50
50
|
getWorkspacePackagePaths: () => import_get_workspace_package_paths.getWorkspacePackagePaths,
|
|
51
51
|
getWorkspaces: () => import_get_workspaces.getWorkspaces,
|
|
52
|
+
isExperimentalService: () => import_build_utils.isExperimentalService,
|
|
53
|
+
isExperimentalServiceV2: () => import_build_utils.isExperimentalServiceV2,
|
|
52
54
|
isOfficialRuntime: () => import_is_official_runtime.isOfficialRuntime,
|
|
53
55
|
isRouteOwningBuilder: () => import_utils.isRouteOwningBuilder,
|
|
54
56
|
isStaticBuild: () => import_utils.isStaticBuild,
|
|
55
57
|
isStaticRuntime: () => import_is_official_runtime.isStaticRuntime,
|
|
56
58
|
monorepoManagers: () => import_monorepo_managers.monorepoManagers,
|
|
57
59
|
packageManagers: () => import_package_managers.packageManagers,
|
|
60
|
+
resolveAllConfiguredServicesV2: () => import_resolve_v2.resolveAllConfiguredServicesV2,
|
|
61
|
+
resolveConfiguredServiceV2: () => import_resolve_v2.resolveConfiguredServiceV2,
|
|
62
|
+
validateServiceConfigV2: () => import_resolve_v2.validateServiceConfigV2,
|
|
58
63
|
workspaceManagers: () => import_workspace_managers.workspaceManagers
|
|
59
64
|
});
|
|
60
65
|
module.exports = __toCommonJS(src_exports);
|
|
61
66
|
var import_detect_builders = require("./detect-builders");
|
|
62
67
|
var import_detect_services = require("./services/detect-services");
|
|
68
|
+
var import_resolve_v2 = require("./services/resolve-v2");
|
|
69
|
+
var import_build_utils = require("@vercel/build-utils");
|
|
63
70
|
var import_auto_detect = require("./services/auto-detect");
|
|
64
71
|
var import_utils = require("./services/utils");
|
|
65
72
|
var import_get_services_builders = require("./services/get-services-builders");
|
|
@@ -109,12 +116,17 @@ var import_detect_instrumentation = require("./detect-instrumentation");
|
|
|
109
116
|
getServicesBuilders,
|
|
110
117
|
getWorkspacePackagePaths,
|
|
111
118
|
getWorkspaces,
|
|
119
|
+
isExperimentalService,
|
|
120
|
+
isExperimentalServiceV2,
|
|
112
121
|
isOfficialRuntime,
|
|
113
122
|
isRouteOwningBuilder,
|
|
114
123
|
isStaticBuild,
|
|
115
124
|
isStaticRuntime,
|
|
116
125
|
monorepoManagers,
|
|
117
126
|
packageManagers,
|
|
127
|
+
resolveAllConfiguredServicesV2,
|
|
128
|
+
resolveConfiguredServiceV2,
|
|
129
|
+
validateServiceConfigV2,
|
|
118
130
|
workspaceManagers,
|
|
119
131
|
...require("./monorepos/get-monorepo-default-settings")
|
|
120
132
|
});
|
|
@@ -33,4 +33,4 @@ export declare function detectServices(options: DetectServicesOptions): Promise<
|
|
|
33
33
|
* Internal cron callback routes under `/_svc/{serviceName}/crons/{entry}/{handler}`
|
|
34
34
|
* that rewrite to `/_svc/{serviceName}/index`.
|
|
35
35
|
*/
|
|
36
|
-
export declare function generateServicesRoutes(
|
|
36
|
+
export declare function generateServicesRoutes(allServices: Service[]): ServicesRoutes;
|
|
@@ -26,6 +26,7 @@ var import_build_utils = require("@vercel/build-utils");
|
|
|
26
26
|
var import_routing_utils = require("@vercel/routing-utils");
|
|
27
27
|
var import_utils = require("./utils");
|
|
28
28
|
var import_resolve = require("./resolve");
|
|
29
|
+
var import_resolve_v2 = require("./resolve-v2");
|
|
29
30
|
var import_auto_detect = require("./auto-detect");
|
|
30
31
|
var import_detect_railway = require("./detect-railway");
|
|
31
32
|
var import_detect_render = require("./detect-render");
|
|
@@ -90,7 +91,8 @@ async function detectServices(options) {
|
|
|
90
91
|
fs,
|
|
91
92
|
workPath,
|
|
92
93
|
detectEntrypoint,
|
|
93
|
-
configuredServices: providedConfiguredServices
|
|
94
|
+
configuredServices: providedConfiguredServices,
|
|
95
|
+
configuredServicesType
|
|
94
96
|
} = options;
|
|
95
97
|
const scopedFs = workPath ? fs.chdir(workPath) : fs;
|
|
96
98
|
const { config: vercelConfig, error: configError } = await (0, import_utils.readVercelConfig)(scopedFs);
|
|
@@ -105,6 +107,23 @@ async function detectServices(options) {
|
|
|
105
107
|
});
|
|
106
108
|
}
|
|
107
109
|
const hasProvidedConfiguredServices = providedConfiguredServices && Object.keys(providedConfiguredServices).length > 0;
|
|
110
|
+
const experimentalServicesV2 = hasProvidedConfiguredServices && configuredServicesType === "experimentalServicesV2" ? providedConfiguredServices : hasProvidedConfiguredServices ? void 0 : vercelConfig?.experimentalServicesV2;
|
|
111
|
+
if (experimentalServicesV2 && Object.keys(experimentalServicesV2).length > 0) {
|
|
112
|
+
const result2 = await (0, import_resolve_v2.resolveAllConfiguredServicesV2)(
|
|
113
|
+
experimentalServicesV2,
|
|
114
|
+
scopedFs
|
|
115
|
+
);
|
|
116
|
+
return withResolvedResult({
|
|
117
|
+
services: result2.services,
|
|
118
|
+
source: "configured",
|
|
119
|
+
// V2 uses explicit `bindings`, so no implicit `{NAME}_URL` injection.
|
|
120
|
+
useImplicitEnvInjection: false,
|
|
121
|
+
// V2 routes are explicitly carried per-service to output them separately.
|
|
122
|
+
routes: emptyRoutes(),
|
|
123
|
+
errors: result2.errors,
|
|
124
|
+
warnings: []
|
|
125
|
+
});
|
|
126
|
+
}
|
|
108
127
|
const configuredServices = hasProvidedConfiguredServices ? providedConfiguredServices : vercelConfig?.experimentalServices;
|
|
109
128
|
const hasConfiguredServices = configuredServices && Object.keys(configuredServices).length > 0;
|
|
110
129
|
if (!hasConfiguredServices) {
|
|
@@ -210,7 +229,8 @@ async function tryResolveInferred(detectResult, source, scopedFs) {
|
|
|
210
229
|
inferred
|
|
211
230
|
);
|
|
212
231
|
}
|
|
213
|
-
function generateServicesRoutes(
|
|
232
|
+
function generateServicesRoutes(allServices) {
|
|
233
|
+
const services = allServices.filter(import_build_utils.isExperimentalService);
|
|
214
234
|
const hostRewrites = [];
|
|
215
235
|
const rewrites = [];
|
|
216
236
|
const defaults = [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Route } from '@vercel/routing-utils';
|
|
2
2
|
import type { Builder } from '@vercel/build-utils';
|
|
3
|
-
import type { ConfiguredServices,
|
|
3
|
+
import type { ConfiguredServices, ConfiguredServicesType, Service } from './types';
|
|
4
4
|
export interface ErrorResponse {
|
|
5
5
|
code: string;
|
|
6
6
|
message: string;
|
|
@@ -10,7 +10,7 @@ export interface ErrorResponse {
|
|
|
10
10
|
export interface GetServicesBuildersOptions {
|
|
11
11
|
workPath?: string;
|
|
12
12
|
configuredServices?: ConfiguredServices;
|
|
13
|
-
configuredServicesType?:
|
|
13
|
+
configuredServicesType?: ConfiguredServicesType;
|
|
14
14
|
projectFramework?: string | null;
|
|
15
15
|
}
|
|
16
16
|
export interface ServicesBuildersResult {
|
|
@@ -23,7 +23,7 @@ export interface ServicesBuildersResult {
|
|
|
23
23
|
redirectRoutes: Route[] | null;
|
|
24
24
|
rewriteRoutes: Route[] | null;
|
|
25
25
|
errorRoutes: Route[] | null;
|
|
26
|
-
services?:
|
|
26
|
+
services?: Service[];
|
|
27
27
|
useImplicitEnvInjection?: boolean;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ExperimentalServiceV2, ExperimentalServiceV2Config, ExperimentalServicesV2, ServiceDetectionError } from './types';
|
|
2
|
+
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
3
|
+
export declare function validateServiceConfigV2(name: string, config: ExperimentalServiceV2Config): ServiceDetectionError | null;
|
|
4
|
+
export declare function resolveConfiguredServiceV2(name: string, config: ExperimentalServiceV2Config, fs: DetectorFilesystem): Promise<{
|
|
5
|
+
service?: ExperimentalServiceV2;
|
|
6
|
+
error?: ServiceDetectionError;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function resolveAllConfiguredServicesV2(services: ExperimentalServicesV2, fs: DetectorFilesystem): Promise<{
|
|
9
|
+
services: ExperimentalServiceV2[];
|
|
10
|
+
errors: ServiceDetectionError[];
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var resolve_v2_exports = {};
|
|
20
|
+
__export(resolve_v2_exports, {
|
|
21
|
+
resolveAllConfiguredServicesV2: () => resolveAllConfiguredServicesV2,
|
|
22
|
+
resolveConfiguredServiceV2: () => resolveConfiguredServiceV2,
|
|
23
|
+
validateServiceConfigV2: () => validateServiceConfigV2
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(resolve_v2_exports);
|
|
26
|
+
var import_path = require("path");
|
|
27
|
+
var import_build_utils = require("@vercel/build-utils");
|
|
28
|
+
var import_frameworks = require("@vercel/frameworks");
|
|
29
|
+
var import_types = require("./types");
|
|
30
|
+
var import_resolve = require("./resolve");
|
|
31
|
+
var import_utils = require("./utils");
|
|
32
|
+
const frameworksBySlug = new Map(import_frameworks.frameworkList.map((f) => [f.slug, f]));
|
|
33
|
+
const SERVICE_NAME_REGEX = /^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
|
|
34
|
+
function validateServiceConfigV2(name, config) {
|
|
35
|
+
if (!SERVICE_NAME_REGEX.test(name)) {
|
|
36
|
+
return {
|
|
37
|
+
code: "INVALID_SERVICE_NAME",
|
|
38
|
+
message: `Service name "${name}" is invalid. Names must start with a letter, end with an alphanumeric character, and contain only alphanumeric characters, hyphens, and underscores.`,
|
|
39
|
+
serviceName: name
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (!config || typeof config !== "object") {
|
|
43
|
+
return {
|
|
44
|
+
code: "INVALID_SERVICE_CONFIG",
|
|
45
|
+
message: `Service "${name}" has an invalid configuration. Expected an object.`,
|
|
46
|
+
serviceName: name
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (typeof config.root !== "string" || config.root.length === 0) {
|
|
50
|
+
return {
|
|
51
|
+
code: "MISSING_ROOT",
|
|
52
|
+
message: `Service "${name}" must specify a "root".`,
|
|
53
|
+
serviceName: name
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const normalizedRoot = import_path.posix.normalize(config.root);
|
|
57
|
+
if (normalizedRoot.startsWith("/")) {
|
|
58
|
+
return {
|
|
59
|
+
code: "INVALID_ROOT",
|
|
60
|
+
message: `Service "${name}" has invalid "root" "${config.root}". Must be a relative path.`,
|
|
61
|
+
serviceName: name
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (normalizedRoot === ".." || normalizedRoot.startsWith("../")) {
|
|
65
|
+
return {
|
|
66
|
+
code: "INVALID_ROOT",
|
|
67
|
+
message: `Service "${name}" has invalid "root" "${config.root}". Must not escape the project root.`,
|
|
68
|
+
serviceName: name
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (config.runtime && !(config.runtime in import_types.RUNTIME_BUILDERS)) {
|
|
72
|
+
return {
|
|
73
|
+
code: "INVALID_RUNTIME",
|
|
74
|
+
message: `Service "${name}" has invalid runtime "${config.runtime}".`,
|
|
75
|
+
serviceName: name
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (config.framework && !frameworksBySlug.has(config.framework)) {
|
|
79
|
+
return {
|
|
80
|
+
code: "INVALID_FRAMEWORK",
|
|
81
|
+
message: `Service "${name}" has invalid framework "${config.framework}".`,
|
|
82
|
+
serviceName: name
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (config.runtime && config.framework) {
|
|
86
|
+
const frameworkRuntime = (0, import_utils.inferRuntimeFromFramework)(config.framework);
|
|
87
|
+
if (frameworkRuntime && frameworkRuntime !== config.runtime) {
|
|
88
|
+
return {
|
|
89
|
+
code: "RUNTIME_FRAMEWORK_MISMATCH",
|
|
90
|
+
message: `Service "${name}" has conflicting runtime/framework: runtime "${config.runtime}" is incompatible with framework "${config.framework}" (runtime "${frameworkRuntime}").`,
|
|
91
|
+
serviceName: name
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!config.framework && !config.entrypoint) {
|
|
96
|
+
return {
|
|
97
|
+
code: "MISSING_SERVICE_CONFIG",
|
|
98
|
+
message: `Service "${name}" must specify "framework" or "entrypoint".`,
|
|
99
|
+
serviceName: name
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
async function resolveConfiguredServiceV2(name, config, fs) {
|
|
105
|
+
const root = config.root;
|
|
106
|
+
const normalizedRoot = import_path.posix.normalize(root);
|
|
107
|
+
const serviceFsResult = normalizedRoot === "." ? { fs } : await (0, import_resolve.getServiceFs)(fs, name, root);
|
|
108
|
+
if (serviceFsResult.error) {
|
|
109
|
+
return { error: serviceFsResult.error };
|
|
110
|
+
}
|
|
111
|
+
const serviceFs = serviceFsResult.fs;
|
|
112
|
+
const rawEntrypoint = config.entrypoint;
|
|
113
|
+
const moduleAttr = typeof rawEntrypoint === "string" ? (0, import_resolve.parsePyModuleAttrEntrypoint)(rawEntrypoint) : null;
|
|
114
|
+
let normalizedEntrypoint;
|
|
115
|
+
let entrypointIsDirectory = false;
|
|
116
|
+
if (typeof rawEntrypoint === "string") {
|
|
117
|
+
const entrypointToResolve = moduleAttr ? moduleAttr.filePath : rawEntrypoint;
|
|
118
|
+
const resolved = await (0, import_resolve.resolveEntrypointPath)({
|
|
119
|
+
fs: serviceFs,
|
|
120
|
+
serviceName: name,
|
|
121
|
+
entrypoint: entrypointToResolve
|
|
122
|
+
});
|
|
123
|
+
if (resolved.error) {
|
|
124
|
+
return { error: resolved.error };
|
|
125
|
+
}
|
|
126
|
+
normalizedEntrypoint = resolved.entrypoint?.normalized;
|
|
127
|
+
entrypointIsDirectory = Boolean(resolved.entrypoint?.isDirectory);
|
|
128
|
+
}
|
|
129
|
+
const entrypointFile = entrypointIsDirectory || !normalizedEntrypoint ? void 0 : normalizedEntrypoint;
|
|
130
|
+
const inferredRuntime = (0, import_utils.inferServiceRuntime)({
|
|
131
|
+
runtime: config.runtime,
|
|
132
|
+
framework: config.framework,
|
|
133
|
+
entrypoint: entrypointFile
|
|
134
|
+
});
|
|
135
|
+
let framework = config.framework;
|
|
136
|
+
if (!framework && normalizedEntrypoint) {
|
|
137
|
+
const workspace = entrypointIsDirectory ? normalizedEntrypoint : import_path.posix.dirname(normalizedEntrypoint) || ".";
|
|
138
|
+
const detection = await (0, import_resolve.detectFrameworkFromWorkspace)({
|
|
139
|
+
fs: serviceFs,
|
|
140
|
+
workspace,
|
|
141
|
+
serviceName: name,
|
|
142
|
+
runtime: inferredRuntime
|
|
143
|
+
});
|
|
144
|
+
if (detection.error) {
|
|
145
|
+
return { error: detection.error };
|
|
146
|
+
}
|
|
147
|
+
framework = detection.framework;
|
|
148
|
+
}
|
|
149
|
+
if (entrypointIsDirectory && !framework) {
|
|
150
|
+
return {
|
|
151
|
+
error: {
|
|
152
|
+
code: "MISSING_SERVICE_FRAMEWORK",
|
|
153
|
+
message: `Service "${name}" uses directory entrypoint "${config.entrypoint}" but no framework could be detected. Specify "framework" explicitly or use a file entrypoint.`,
|
|
154
|
+
serviceName: name
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const frameworkDefinition = framework ? frameworksBySlug.get(framework) : void 0;
|
|
159
|
+
let builderUse;
|
|
160
|
+
let builderSrc;
|
|
161
|
+
if (framework) {
|
|
162
|
+
builderUse = (0, import_build_utils.isNodeBackendFramework)(framework) ? "@vercel/backends" : frameworkDefinition?.useRuntime?.use || "@vercel/static-build";
|
|
163
|
+
builderSrc = entrypointFile || frameworkDefinition?.useRuntime?.src || "package.json";
|
|
164
|
+
} else {
|
|
165
|
+
if (!inferredRuntime) {
|
|
166
|
+
return {
|
|
167
|
+
error: {
|
|
168
|
+
code: "MISSING_SERVICE_CONFIG",
|
|
169
|
+
message: `Service "${name}" must specify "framework" or a runtime-resolvable "entrypoint".`,
|
|
170
|
+
serviceName: name
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
builderUse = inferredRuntime === "node" ? "@vercel/backends" : (0, import_utils.getBuilderForRuntime)(inferredRuntime);
|
|
175
|
+
builderSrc = entrypointFile;
|
|
176
|
+
}
|
|
177
|
+
const isRoot = normalizedRoot === ".";
|
|
178
|
+
const projectRelativeSrc = isRoot ? builderSrc : import_path.posix.join(normalizedRoot, builderSrc);
|
|
179
|
+
const builderConfig = { zeroConfig: true };
|
|
180
|
+
if (builderUse === "@vercel/backends") {
|
|
181
|
+
builderConfig.serviceName = name;
|
|
182
|
+
}
|
|
183
|
+
if (framework) {
|
|
184
|
+
builderConfig.framework = framework;
|
|
185
|
+
}
|
|
186
|
+
if (!isRoot) {
|
|
187
|
+
builderConfig.workspace = normalizedRoot;
|
|
188
|
+
}
|
|
189
|
+
if (moduleAttr) {
|
|
190
|
+
builderConfig.handlerFunction = moduleAttr.attrName;
|
|
191
|
+
}
|
|
192
|
+
const runtime = import_types.STATIC_BUILDERS.has(builderUse) ? void 0 : inferredRuntime;
|
|
193
|
+
return {
|
|
194
|
+
service: {
|
|
195
|
+
schema: "experimentalServicesV2",
|
|
196
|
+
name,
|
|
197
|
+
root,
|
|
198
|
+
framework,
|
|
199
|
+
runtime,
|
|
200
|
+
entrypoint: entrypointFile,
|
|
201
|
+
builder: {
|
|
202
|
+
src: projectRelativeSrc,
|
|
203
|
+
use: builderUse,
|
|
204
|
+
config: builderConfig
|
|
205
|
+
},
|
|
206
|
+
installCommand: config.installCommand,
|
|
207
|
+
buildCommand: config.buildCommand,
|
|
208
|
+
devCommand: config.devCommand,
|
|
209
|
+
ignoreCommand: config.ignoreCommand,
|
|
210
|
+
outputDirectory: config.outputDirectory,
|
|
211
|
+
bindings: config.bindings,
|
|
212
|
+
functions: config.functions,
|
|
213
|
+
headers: config.headers,
|
|
214
|
+
redirects: config.redirects,
|
|
215
|
+
rewrites: config.rewrites,
|
|
216
|
+
routes: config.routes,
|
|
217
|
+
cleanUrls: config.cleanUrls,
|
|
218
|
+
trailingSlash: config.trailingSlash
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
async function resolveAllConfiguredServicesV2(services, fs) {
|
|
223
|
+
const resolved = [];
|
|
224
|
+
const errors = [];
|
|
225
|
+
for (const name of Object.keys(services)) {
|
|
226
|
+
const config = services[name];
|
|
227
|
+
const validationError = validateServiceConfigV2(name, config);
|
|
228
|
+
if (validationError) {
|
|
229
|
+
errors.push(validationError);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const { service, error } = await resolveConfiguredServiceV2(
|
|
233
|
+
name,
|
|
234
|
+
config,
|
|
235
|
+
fs
|
|
236
|
+
);
|
|
237
|
+
if (error) {
|
|
238
|
+
errors.push(error);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (service) {
|
|
242
|
+
resolved.push(service);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const serviceNames = new Set(Object.keys(services));
|
|
246
|
+
for (const service of resolved) {
|
|
247
|
+
for (const binding of service.bindings ?? []) {
|
|
248
|
+
if (!serviceNames.has(binding.service)) {
|
|
249
|
+
errors.push({
|
|
250
|
+
code: "UNKNOWN_SERVICE_BINDING",
|
|
251
|
+
message: `Service "${service.name}" declares a binding to unknown service "${binding.service}".`,
|
|
252
|
+
serviceName: service.name
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return { services: resolved, errors };
|
|
258
|
+
}
|
|
259
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
260
|
+
0 && (module.exports = {
|
|
261
|
+
resolveAllConfiguredServicesV2,
|
|
262
|
+
resolveConfiguredServiceV2,
|
|
263
|
+
validateServiceConfigV2
|
|
264
|
+
});
|
|
@@ -1,10 +1,26 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ExperimentalService, ConfiguredServices, ExperimentalServiceConfig, ServiceDetectionError, ServiceRuntime } from './types';
|
|
2
2
|
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
3
|
+
export declare function parsePyModuleAttrEntrypoint(entrypoint: string): {
|
|
4
|
+
attrName: string;
|
|
5
|
+
filePath: string;
|
|
6
|
+
} | null;
|
|
3
7
|
type ConfiguredServiceConfig = ExperimentalServiceConfig;
|
|
4
8
|
interface ResolvedEntrypointPath {
|
|
5
9
|
normalized: string;
|
|
6
10
|
isDirectory: boolean;
|
|
7
11
|
}
|
|
12
|
+
export declare function getServiceFs(fs: DetectorFilesystem, serviceName: string, root?: string): Promise<{
|
|
13
|
+
fs: DetectorFilesystem;
|
|
14
|
+
error?: ServiceDetectionError;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function resolveEntrypointPath({ fs, serviceName, entrypoint, }: {
|
|
17
|
+
fs: DetectorFilesystem;
|
|
18
|
+
serviceName: string;
|
|
19
|
+
entrypoint: string;
|
|
20
|
+
}): Promise<{
|
|
21
|
+
entrypoint?: ResolvedEntrypointPath;
|
|
22
|
+
error?: ServiceDetectionError;
|
|
23
|
+
}>;
|
|
8
24
|
type RoutePrefixSource = 'configured' | 'generated';
|
|
9
25
|
interface ResolveConfiguredServiceOptions {
|
|
10
26
|
name: string;
|
|
@@ -19,6 +35,20 @@ interface ResolveConfiguredServiceOptions {
|
|
|
19
35
|
interface ResolveAllConfiguredServicesOptions {
|
|
20
36
|
requireFileEntrypointForBackendRuntimes?: boolean;
|
|
21
37
|
}
|
|
38
|
+
export declare function inferWorkspaceFromNearestManifest({ fs, entrypoint, runtime, }: {
|
|
39
|
+
fs: DetectorFilesystem;
|
|
40
|
+
entrypoint?: string;
|
|
41
|
+
runtime?: ServiceRuntime;
|
|
42
|
+
}): Promise<string | undefined>;
|
|
43
|
+
export declare function detectFrameworkFromWorkspace({ fs, workspace, serviceName, runtime, }: {
|
|
44
|
+
fs: DetectorFilesystem;
|
|
45
|
+
workspace: string;
|
|
46
|
+
serviceName: string;
|
|
47
|
+
runtime?: ServiceRuntime;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
framework?: string;
|
|
50
|
+
error?: ServiceDetectionError;
|
|
51
|
+
}>;
|
|
22
52
|
/**
|
|
23
53
|
* Validate a service configuration from vercel.json services.
|
|
24
54
|
*/
|
|
@@ -27,13 +57,13 @@ export declare function validateServiceEntrypoint(name: string, config: Configur
|
|
|
27
57
|
/**
|
|
28
58
|
* Resolve a single service from user configuration.
|
|
29
59
|
*/
|
|
30
|
-
export declare function resolveConfiguredService(options: ResolveConfiguredServiceOptions): Promise<
|
|
60
|
+
export declare function resolveConfiguredService(options: ResolveConfiguredServiceOptions): Promise<ExperimentalService>;
|
|
31
61
|
/**
|
|
32
62
|
* Resolve all services from vercel.json services.
|
|
33
63
|
* Validates each service configuration.
|
|
34
64
|
*/
|
|
35
65
|
export declare function resolveAllConfiguredServices(services: ConfiguredServices, fs: DetectorFilesystem, routePrefixSource?: RoutePrefixSource, options?: ResolveAllConfiguredServicesOptions): Promise<{
|
|
36
|
-
services:
|
|
66
|
+
services: ExperimentalService[];
|
|
37
67
|
errors: ServiceDetectionError[];
|
|
38
68
|
}>;
|
|
39
69
|
export {};
|
package/dist/services/resolve.js
CHANGED
|
@@ -18,8 +18,13 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var resolve_exports = {};
|
|
20
20
|
__export(resolve_exports, {
|
|
21
|
+
detectFrameworkFromWorkspace: () => detectFrameworkFromWorkspace,
|
|
22
|
+
getServiceFs: () => getServiceFs,
|
|
23
|
+
inferWorkspaceFromNearestManifest: () => inferWorkspaceFromNearestManifest,
|
|
24
|
+
parsePyModuleAttrEntrypoint: () => parsePyModuleAttrEntrypoint,
|
|
21
25
|
resolveAllConfiguredServices: () => resolveAllConfiguredServices,
|
|
22
26
|
resolveConfiguredService: () => resolveConfiguredService,
|
|
27
|
+
resolveEntrypointPath: () => resolveEntrypointPath,
|
|
23
28
|
validateServiceConfig: () => validateServiceConfig,
|
|
24
29
|
validateServiceEntrypoint: () => validateServiceEntrypoint
|
|
25
30
|
});
|
|
@@ -666,6 +671,7 @@ async function resolveConfiguredService(options) {
|
|
|
666
671
|
builderConfig.handlerFunction = moduleAttrParsed.attrName;
|
|
667
672
|
}
|
|
668
673
|
return {
|
|
674
|
+
schema: "experimentalServices",
|
|
669
675
|
name,
|
|
670
676
|
type,
|
|
671
677
|
trigger,
|
|
@@ -870,8 +876,13 @@ function validateEnvRefs(env, serviceName, servicesByName, errors) {
|
|
|
870
876
|
}
|
|
871
877
|
// Annotate the CommonJS export names for ESM import in node:
|
|
872
878
|
0 && (module.exports = {
|
|
879
|
+
detectFrameworkFromWorkspace,
|
|
880
|
+
getServiceFs,
|
|
881
|
+
inferWorkspaceFromNearestManifest,
|
|
882
|
+
parsePyModuleAttrEntrypoint,
|
|
873
883
|
resolveAllConfiguredServices,
|
|
874
884
|
resolveConfiguredService,
|
|
885
|
+
resolveEntrypointPath,
|
|
875
886
|
validateServiceConfig,
|
|
876
887
|
validateServiceEntrypoint
|
|
877
888
|
});
|
package/dist/services/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Route } from '@vercel/routing-utils';
|
|
2
|
-
import type { DetectEntrypointFn, EnvVar, EnvVars, ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ServiceRuntime, ServiceType, ServiceRefEnvVar, Service, Builder } from '@vercel/build-utils';
|
|
2
|
+
import type { DetectEntrypointFn, EnvVar, EnvVars, ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ExperimentalServiceV2Config, ExperimentalServicesV2, ExperimentalServiceV2Binding, ExperimentalService, ExperimentalServiceV2, ServiceRuntime, ServiceType, ServiceRefEnvVar, Service, Builder } from '@vercel/build-utils';
|
|
3
3
|
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
4
|
-
export type { DetectEntrypointFn, EnvVar, EnvVars, ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ServiceRuntime, ServiceType, ServiceRefEnvVar, Service, Builder, };
|
|
4
|
+
export type { DetectEntrypointFn, EnvVar, EnvVars, ExperimentalServiceConfig, ExperimentalServiceGroups, ExperimentalServices, ExperimentalServiceV2Config, ExperimentalServicesV2, ExperimentalServiceV2Binding, ExperimentalService, ExperimentalServiceV2, ServiceRuntime, ServiceType, ServiceRefEnvVar, Service, Builder, };
|
|
5
5
|
/**
|
|
6
6
|
* @deprecated Use `Service` instead
|
|
7
7
|
*/
|
|
@@ -9,7 +9,7 @@ export type ResolvedService = Service;
|
|
|
9
9
|
export interface DetectServicesOptions {
|
|
10
10
|
fs: DetectorFilesystem;
|
|
11
11
|
configuredServices?: ConfiguredServices;
|
|
12
|
-
configuredServicesType?:
|
|
12
|
+
configuredServicesType?: ConfiguredServicesType;
|
|
13
13
|
/**
|
|
14
14
|
* Working directory path (relative to fs root).
|
|
15
15
|
* If provided, vercel.json is read from this path.
|
|
@@ -42,7 +42,8 @@ export interface ServicesRoutes {
|
|
|
42
42
|
*/
|
|
43
43
|
workers: Route[];
|
|
44
44
|
}
|
|
45
|
-
export type
|
|
45
|
+
export type ConfiguredServicesType = 'experimentalServices' | 'experimentalServicesV2';
|
|
46
|
+
export type ConfiguredServices = ExperimentalServices | ExperimentalServicesV2;
|
|
46
47
|
export type InferredServicesConfig = ExperimentalServices;
|
|
47
48
|
export interface ResolvedServicesResult {
|
|
48
49
|
services: Service[];
|
|
@@ -55,7 +56,7 @@ export interface ResolvedServicesResult {
|
|
|
55
56
|
export interface InferredServicesResult {
|
|
56
57
|
source: 'layout' | 'procfile' | 'railway' | 'render';
|
|
57
58
|
config: InferredServicesConfig;
|
|
58
|
-
services:
|
|
59
|
+
services: ExperimentalService[];
|
|
59
60
|
warnings: ServiceDetectionWarning[];
|
|
60
61
|
}
|
|
61
62
|
export interface DetectServicesResult extends ResolvedServicesResult {
|
package/dist/services/utils.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { INTERNAL_SERVICE_PREFIX, getInternalServiceFunctionPath, getInternalServiceCronPathPrefix, getInternalServiceCronPath } from '@vercel/build-utils';
|
|
2
2
|
import type { Framework } from '@vercel/frameworks';
|
|
3
3
|
import type { DetectorFilesystem } from '../detectors/filesystem';
|
|
4
|
-
import type { ServiceRuntime, ExperimentalServices, ServiceDetectionError, ServiceDetectionWarning, ResolvedService } from './types';
|
|
4
|
+
import type { ServiceRuntime, ExperimentalServices, ExperimentalServicesV2, ServiceDetectionError, ServiceDetectionWarning, ResolvedService } from './types';
|
|
5
5
|
export declare const DETECTION_FRAMEWORKS: Framework[];
|
|
6
6
|
export { INTERNAL_SERVICE_PREFIX, getInternalServiceFunctionPath, getInternalServiceCronPathPrefix, getInternalServiceCronPath, };
|
|
7
7
|
export declare function hasFile(fs: DetectorFilesystem, filePath: string): Promise<boolean>;
|
|
@@ -56,6 +56,7 @@ export declare function inferServiceRuntime(config: {
|
|
|
56
56
|
export interface ReadVercelConfigResult {
|
|
57
57
|
config: {
|
|
58
58
|
experimentalServices?: ExperimentalServices;
|
|
59
|
+
experimentalServicesV2?: ExperimentalServicesV2;
|
|
59
60
|
} | null;
|
|
60
61
|
error: ServiceDetectionError | null;
|
|
61
62
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/fs-detectors",
|
|
3
|
-
"version": "6.7.
|
|
3
|
+
"version": "6.7.8",
|
|
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.26.6",
|
|
24
23
|
"@vercel/frameworks": "3.27.0",
|
|
25
|
-
"@vercel/
|
|
26
|
-
"@vercel/error-utils": "2.2.0"
|
|
24
|
+
"@vercel/build-utils": "13.27.1",
|
|
25
|
+
"@vercel/error-utils": "2.2.0",
|
|
26
|
+
"@vercel/routing-utils": "6.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/glob": "7.2.0",
|