@vercel/fs-detectors 6.15.10 → 7.0.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.
@@ -1,6 +1,6 @@
1
1
  import type { Route } from '@vercel/routing-utils';
2
2
  import { type Framework } from '@vercel/frameworks';
3
- import type { PackageJson, Builder, BuilderFunctions, ExperimentalServices, ExperimentalServicesV2, Services, ProjectSettings, Service } from '@vercel/build-utils';
3
+ import type { PackageJson, Builder, BuilderFunctions, ProjectSettings } from '@vercel/build-utils';
4
4
  /**
5
5
  * Pattern for finding all supported middleware files.
6
6
  */
@@ -27,9 +27,6 @@ export interface ProxyConfig {
27
27
  export interface Options {
28
28
  tag?: string;
29
29
  functions?: BuilderFunctions;
30
- experimentalServices?: ExperimentalServices;
31
- services?: Services;
32
- experimentalServicesV2?: ExperimentalServicesV2;
33
30
  ignoreBuildScript?: boolean;
34
31
  projectSettings?: ProjectSettings;
35
32
  cleanUrls?: boolean;
@@ -47,15 +44,10 @@ export declare function detectBuilders(files: string[], pkg?: PackageJson | unde
47
44
  builders: Builder[] | null;
48
45
  errors: ErrorResponse[] | null;
49
46
  warnings: ErrorResponse[];
50
- hostRewriteRoutes?: Route[] | null;
51
47
  defaultRoutes: Route[] | null;
52
- fallbackRoutes?: Route[] | null;
53
48
  redirectRoutes: Route[] | null;
54
49
  rewriteRoutes: Route[] | null;
55
50
  errorRoutes: Route[] | null;
56
- services?: Service[];
57
- experimentalServicesV2?: Services;
58
- useImplicitEnvInjection?: boolean;
59
51
  }>;
60
52
  export declare function getProxyBuilder(proxy: ProxyConfig, tag?: string, functions?: BuilderFunctions): Builder;
61
53
  /**
@@ -64,3 +56,4 @@ export declare function getProxyBuilder(proxy: ProxyConfig, tag?: string, functi
64
56
  * `vercel.json` before builders are detected.
65
57
  */
66
58
  export declare function validateProxyConfig(proxy: ProxyConfig): ErrorResponse | null;
59
+ export declare function validateProxy(options: Pick<Options, 'proxy'>, files: string[], framework: string | null | undefined): ErrorResponse | null;
@@ -38,6 +38,7 @@ __export(detect_builders_exports, {
38
38
  detectOutputDirectory: () => detectOutputDirectory,
39
39
  getProxyBuilder: () => getProxyBuilder,
40
40
  sortFiles: () => sortFiles,
41
+ validateProxy: () => validateProxy,
41
42
  validateProxyConfig: () => validateProxyConfig
42
43
  });
43
44
  module.exports = __toCommonJS(detect_builders_exports);
@@ -48,7 +49,6 @@ var import_frameworks = require("@vercel/frameworks");
48
49
  var import_is_official_runtime = require("./is-official-runtime");
49
50
  var import_build_utils = require("@vercel/build-utils");
50
51
  var import_python = require("./python");
51
- var import_get_services_builders = require("./services/get-services-builders");
52
52
  const REGEX_MIDDLEWARE_FILES = "middleware.[jt]s";
53
53
  const VERCEL_PLATFORM_FILES = [
54
54
  "api/**",
@@ -121,28 +121,7 @@ function detectOutputDirectory(builders) {
121
121
  return publicBuilder ? publicBuilder.src.replace("/**/*", "") : null;
122
122
  }
123
123
  async function detectBuilders(files, pkg, options = {}) {
124
- const {
125
- experimentalServices: experimentalServicesV1,
126
- services,
127
- experimentalServicesV2,
128
- projectSettings = {}
129
- } = options;
130
- if (services != null && experimentalServicesV2 != null) {
131
- return {
132
- builders: null,
133
- errors: [
134
- {
135
- code: "SERVICES_AND_EXPERIMENTAL_SERVICES_V2",
136
- message: "The `services` option cannot be used in conjunction with its deprecated alias `experimentalServicesV2`. Please use only `services`."
137
- }
138
- ],
139
- warnings: [],
140
- defaultRoutes: null,
141
- redirectRoutes: null,
142
- rewriteRoutes: null,
143
- errorRoutes: null
144
- };
145
- }
124
+ const { projectSettings = {} } = options;
146
125
  const { framework } = projectSettings;
147
126
  const proxyError = validateProxy(options, files, framework);
148
127
  if (proxyError) {
@@ -156,30 +135,6 @@ async function detectBuilders(files, pkg, options = {}) {
156
135
  errorRoutes: null
157
136
  };
158
137
  }
159
- const servicesConfig = services ?? experimentalServicesV2;
160
- const configuredServices = servicesConfig ?? experimentalServicesV1;
161
- const configuredServicesType = servicesConfig ? services ? "services" : "experimentalServicesV2" : "experimentalServices";
162
- const hasServicesConfig = configuredServices != null && typeof configuredServices === "object";
163
- if (hasServicesConfig || framework === "services") {
164
- const result = await (0, import_get_services_builders.getServicesBuilders)({
165
- workPath: options.workPath,
166
- configuredServices,
167
- configuredServicesType,
168
- projectFramework: framework
169
- });
170
- if (configuredServices != null) {
171
- result.warnings.push(
172
- ...(0, import_get_services_builders.warnIgnoredDirectories)(files, configuredServices)
173
- );
174
- }
175
- if (!result.errors && options.proxy) {
176
- result.builders = [
177
- getProxyBuilder(options.proxy, options.tag, options.functions),
178
- ...result.builders ?? []
179
- ];
180
- }
181
- return result;
182
- }
183
138
  const errors = [];
184
139
  const warnings = [];
185
140
  let apiBuilders = [];
@@ -1031,5 +986,6 @@ function sortFilesBySegmentCount(fileA, fileB) {
1031
986
  detectOutputDirectory,
1032
987
  getProxyBuilder,
1033
988
  sortFiles,
989
+ validateProxy,
1034
990
  validateProxyConfig
1035
991
  });
package/dist/index.d.ts CHANGED
@@ -1,12 +1,4 @@
1
- export { builderToFrameworks, detectBuilders, detectOutputDirectory, detectApiDirectory, detectApiExtensions, getProxyBuilder, validateProxyConfig, type Options as DetectBuildersOptions, type ProxyConfig, } from './detect-builders';
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';
5
- export { autoDetectServices } from './services/auto-detect';
6
- export type { AutoDetectOptions, AutoDetectResult, } from './services/auto-detect';
7
- export { isStaticBuild, isRouteOwningBuilder, INTERNAL_SERVICE_PREFIX, getInternalServiceFunctionPath, getInternalServiceCronPath, getInternalServiceCronPathPrefix, getInternalServiceWorkerPath, getInternalServiceWorkerPathPrefix, } from './services/utils';
8
- export { getServicesBuilders } from './services/get-services-builders';
9
- export type { DetectServicesOptions, DetectServicesResult, DetectServicesSource, InferredServiceConfig, InferredServicesConfig, ResolvedServicesResult, InferredServicesResult, ResolvedService, Service, ExperimentalService, ExperimentalServiceV2, ExperimentalServiceV2Config, ExperimentalServicesV2, ExperimentalServiceV2Binding, ServiceBinding, ServiceConfig, Services, ServicesRoutes, ServiceDetectionError, } from './services/types';
1
+ export { builderToFrameworks, detectBuilders, detectOutputDirectory, detectApiDirectory, detectApiExtensions, getProxyBuilder, validateProxyConfig, validateProxy, type Options as DetectBuildersOptions, type ProxyConfig, } from './detect-builders';
10
2
  export { detectFileSystemAPI } from './detect-file-system-api';
11
3
  export { detectFramework, detectFrameworks, detectFrameworkRecord, detectFrameworkVersion, } from './detect-framework';
12
4
  export { getProjectPaths } from './get-project-paths';
package/dist/index.js CHANGED
@@ -22,12 +22,10 @@ __export(src_exports, {
22
22
  DetectorFilesystem: () => import_filesystem.DetectorFilesystem,
23
23
  GetWorkspaceOptions: () => import_get_workspaces.GetWorkspaceOptions,
24
24
  GetWorkspacePackagePathsOptions: () => import_get_workspace_package_paths.GetWorkspacePackagePathsOptions,
25
- INTERNAL_SERVICE_PREFIX: () => import_utils.INTERNAL_SERVICE_PREFIX,
26
25
  LocalFileSystemDetector: () => import_local_file_system_detector.LocalFileSystemDetector,
27
26
  REGEX_NON_VERCEL_PLATFORM_FILES: () => import_detect_builders2.REGEX_NON_VERCEL_PLATFORM_FILES,
28
27
  Workspace: () => import_get_workspaces.Workspace,
29
28
  WorkspaceType: () => import_get_workspaces.WorkspaceType,
30
- autoDetectServices: () => import_auto_detect.autoDetectServices,
31
29
  builderToFrameworks: () => import_detect_builders.builderToFrameworks,
32
30
  detectApiDirectory: () => import_detect_builders.detectApiDirectory,
33
31
  detectApiExtensions: () => import_detect_builders.detectApiExtensions,
@@ -39,40 +37,20 @@ __export(src_exports, {
39
37
  detectFrameworks: () => import_detect_framework.detectFrameworks,
40
38
  detectInstrumentation: () => import_detect_instrumentation.detectInstrumentation,
41
39
  detectOutputDirectory: () => import_detect_builders.detectOutputDirectory,
42
- detectServices: () => import_detect_services.detectServices,
43
- generateServicesRoutes: () => import_detect_services.generateServicesRoutes,
44
- getInternalServiceCronPath: () => import_utils.getInternalServiceCronPath,
45
- getInternalServiceCronPathPrefix: () => import_utils.getInternalServiceCronPathPrefix,
46
- getInternalServiceFunctionPath: () => import_utils.getInternalServiceFunctionPath,
47
- getInternalServiceWorkerPath: () => import_utils.getInternalServiceWorkerPath,
48
- getInternalServiceWorkerPathPrefix: () => import_utils.getInternalServiceWorkerPathPrefix,
49
40
  getProjectPaths: () => import_get_project_paths.getProjectPaths,
50
41
  getProxyBuilder: () => import_detect_builders.getProxyBuilder,
51
- getServicesBuilders: () => import_get_services_builders.getServicesBuilders,
52
42
  getWorkspacePackagePaths: () => import_get_workspace_package_paths.getWorkspacePackagePaths,
53
43
  getWorkspaces: () => import_get_workspaces.getWorkspaces,
54
- isExperimentalService: () => import_build_utils.isExperimentalService,
55
- isExperimentalServiceV2: () => import_build_utils.isExperimentalServiceV2,
56
44
  isOfficialRuntime: () => import_is_official_runtime.isOfficialRuntime,
57
- isRouteOwningBuilder: () => import_utils.isRouteOwningBuilder,
58
- isStaticBuild: () => import_utils.isStaticBuild,
59
45
  isStaticRuntime: () => import_is_official_runtime.isStaticRuntime,
60
46
  monorepoManagers: () => import_monorepo_managers.monorepoManagers,
61
47
  packageManagers: () => import_package_managers.packageManagers,
62
- resolveAllConfiguredServicesV2: () => import_resolve_v2.resolveAllConfiguredServicesV2,
63
- resolveConfiguredServiceV2: () => import_resolve_v2.resolveConfiguredServiceV2,
48
+ validateProxy: () => import_detect_builders.validateProxy,
64
49
  validateProxyConfig: () => import_detect_builders.validateProxyConfig,
65
- validateServiceConfigV2: () => import_resolve_v2.validateServiceConfigV2,
66
50
  workspaceManagers: () => import_workspace_managers.workspaceManagers
67
51
  });
68
52
  module.exports = __toCommonJS(src_exports);
69
53
  var import_detect_builders = require("./detect-builders");
70
- var import_detect_services = require("./services/detect-services");
71
- var import_resolve_v2 = require("./services/resolve-v2");
72
- var import_build_utils = require("@vercel/build-utils");
73
- var import_auto_detect = require("./services/auto-detect");
74
- var import_utils = require("./services/utils");
75
- var import_get_services_builders = require("./services/get-services-builders");
76
54
  var import_detect_file_system_api = require("./detect-file-system-api");
77
55
  var import_detect_framework = require("./detect-framework");
78
56
  var import_get_project_paths = require("./get-project-paths");
@@ -92,12 +70,10 @@ var import_detect_instrumentation = require("./detect-instrumentation");
92
70
  DetectorFilesystem,
93
71
  GetWorkspaceOptions,
94
72
  GetWorkspacePackagePathsOptions,
95
- INTERNAL_SERVICE_PREFIX,
96
73
  LocalFileSystemDetector,
97
74
  REGEX_NON_VERCEL_PLATFORM_FILES,
98
75
  Workspace,
99
76
  WorkspaceType,
100
- autoDetectServices,
101
77
  builderToFrameworks,
102
78
  detectApiDirectory,
103
79
  detectApiExtensions,
@@ -109,30 +85,16 @@ var import_detect_instrumentation = require("./detect-instrumentation");
109
85
  detectFrameworks,
110
86
  detectInstrumentation,
111
87
  detectOutputDirectory,
112
- detectServices,
113
- generateServicesRoutes,
114
- getInternalServiceCronPath,
115
- getInternalServiceCronPathPrefix,
116
- getInternalServiceFunctionPath,
117
- getInternalServiceWorkerPath,
118
- getInternalServiceWorkerPathPrefix,
119
88
  getProjectPaths,
120
89
  getProxyBuilder,
121
- getServicesBuilders,
122
90
  getWorkspacePackagePaths,
123
91
  getWorkspaces,
124
- isExperimentalService,
125
- isExperimentalServiceV2,
126
92
  isOfficialRuntime,
127
- isRouteOwningBuilder,
128
- isStaticBuild,
129
93
  isStaticRuntime,
130
94
  monorepoManagers,
131
95
  packageManagers,
132
- resolveAllConfiguredServicesV2,
133
- resolveConfiguredServiceV2,
96
+ validateProxy,
134
97
  validateProxyConfig,
135
- validateServiceConfigV2,
136
98
  workspaceManagers,
137
99
  ...require("./monorepos/get-monorepo-default-settings")
138
100
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/fs-detectors",
3
- "version": "6.15.10",
3
+ "version": "7.0.0",
4
4
  "description": "Vercel filesystem detectors",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -19,12 +19,11 @@
19
19
  "json5": "2.2.2",
20
20
  "minimatch": "3.1.2",
21
21
  "semver": "6.3.1",
22
- "smol-toml": "1.5.2",
23
- "@vercel/build-utils": "14.2.0",
24
- "@vercel/error-utils": "2.2.1",
22
+ "@vercel/build-utils": "14.3.0",
25
23
  "@vercel/frameworks": "3.32.0",
24
+ "@vercel/routing-utils": "6.5.0",
26
25
  "@vercel/python-analysis": "0.14.0",
27
- "@vercel/routing-utils": "6.5.0"
26
+ "@vercel/error-utils": "2.2.1"
28
27
  },
29
28
  "devDependencies": {
30
29
  "@types/glob": "7.2.0",
@@ -38,7 +37,6 @@
38
37
  "build": "node ../../utils/build.mjs",
39
38
  "test": "vitest run --config ../../vitest.config.mts",
40
39
  "test-unit": "vitest run --config ../../vitest.config.mts test/unit.",
41
- "test-e2e": "vitest run --config ../../vitest.config.mts test/integration.test.ts",
42
40
  "type-check": "tsc --noEmit"
43
41
  }
44
42
  }
@@ -1,46 +0,0 @@
1
- import type { DetectEntrypointFn } from '@vercel/build-utils';
2
- import type { DetectorFilesystem } from '../detectors/filesystem';
3
- import type { InferredServicesConfig, ServiceDetectionError, ServiceDetectionWarning } from './types';
4
- export interface AutoDetectOptions {
5
- fs: DetectorFilesystem;
6
- /**
7
- * Optional callback used to enrich runtime services with a normalized
8
- * entrypoint (file path or `module:attr` reference).
9
- */
10
- detectEntrypoint?: DetectEntrypointFn;
11
- }
12
- export interface AutoDetectResult {
13
- services: InferredServicesConfig | null;
14
- errors: ServiceDetectionError[];
15
- warnings: ServiceDetectionWarning[];
16
- }
17
- /**
18
- * Auto-detect services when services are not configured.
19
- *
20
- * Scans the project for frameworks, supporting multiple layouts:
21
- *
22
- * Frontend at root, backend in backend/:
23
- * project/
24
- * ├── package.json
25
- * └── backend/
26
- *
27
- * Frontend in frontend/, backend in backend/:
28
- * project/
29
- * ├── frontend/
30
- * └── backend/
31
- *
32
- * Frontend in frontend/, backend in services/{service-name}/:
33
- * project/
34
- * ├── frontend/
35
- * └── services/
36
- * ├── service-a/
37
- * └── service-b/
38
- *
39
- * Frontend in apps/web/ monorepo, backend in services/{service-name}/:
40
- * project/
41
- * ├── apps/web/
42
- * └── services/
43
- * ├── service-a/
44
- * └── service-b/
45
- */
46
- export declare function autoDetectServices(options: AutoDetectOptions): Promise<AutoDetectResult>;
@@ -1,268 +0,0 @@
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 auto_detect_exports = {};
20
- __export(auto_detect_exports, {
21
- autoDetectServices: () => autoDetectServices
22
- });
23
- module.exports = __toCommonJS(auto_detect_exports);
24
- var import_detect_framework = require("../detect-framework");
25
- var import_frameworks = require("@vercel/frameworks");
26
- var import_utils = require("./utils");
27
- const FRONTEND_DIR = "frontend";
28
- const APPS_WEB_DIR = "apps/web";
29
- const BACKEND_DIR = "backend";
30
- const SERVICES_DIR = "services";
31
- const FRONTEND_LOCATIONS = [FRONTEND_DIR, APPS_WEB_DIR];
32
- async function autoDetectServices(options) {
33
- const { fs, detectEntrypoint } = options;
34
- const rootFrameworks = await (0, import_detect_framework.detectFrameworks)({
35
- fs,
36
- frameworkList: import_frameworks.frameworkList
37
- });
38
- if (rootFrameworks.length > 1) {
39
- const frameworkNames = rootFrameworks.map((f) => f.name).join(", ");
40
- return {
41
- services: null,
42
- warnings: [],
43
- errors: [
44
- {
45
- code: "MULTIPLE_FRAMEWORKS_ROOT",
46
- message: `Multiple frameworks detected at root: ${frameworkNames}. Use explicit services config.`
47
- }
48
- ]
49
- };
50
- }
51
- if (rootFrameworks.length === 1) {
52
- return detectServicesAtRoot(fs, rootFrameworks[0], detectEntrypoint);
53
- }
54
- for (const frontendLocation of FRONTEND_LOCATIONS) {
55
- const hasFrontendDir = await fs.hasPath(frontendLocation);
56
- if (!hasFrontendDir) {
57
- continue;
58
- }
59
- const frontendFs = fs.chdir(frontendLocation);
60
- const frontendFrameworks = await (0, import_detect_framework.detectFrameworks)({
61
- fs: frontendFs,
62
- frameworkList: import_frameworks.frameworkList
63
- });
64
- if (frontendFrameworks.length > 1) {
65
- const frameworkNames = frontendFrameworks.map((f) => f.name).join(", ");
66
- return {
67
- services: null,
68
- warnings: [],
69
- errors: [
70
- {
71
- code: "MULTIPLE_FRAMEWORKS_SERVICE",
72
- message: `Multiple frameworks detected in ${frontendLocation}/: ${frameworkNames}. Use explicit services config.`
73
- }
74
- ]
75
- };
76
- }
77
- if (frontendFrameworks.length === 1) {
78
- return detectServicesFrontendSubdir(
79
- fs,
80
- frontendFrameworks[0],
81
- frontendLocation,
82
- detectEntrypoint
83
- );
84
- }
85
- }
86
- return {
87
- services: null,
88
- warnings: [],
89
- errors: [
90
- {
91
- code: "NO_SERVICES_CONFIGURED",
92
- message: "No services detected. Configure `services` in vercel.json or ensure a framework exists at project root, frontend/, or apps/web/."
93
- }
94
- ]
95
- };
96
- }
97
- async function detectServicesAtRoot(fs, rootFramework, detectEntrypoint) {
98
- const services = {};
99
- services.frontend = {
100
- root: ".",
101
- framework: rootFramework.slug ?? void 0,
102
- mountPath: "/"
103
- };
104
- const backendResult = await detectBackendServices(fs, detectEntrypoint);
105
- if (backendResult.error) {
106
- return {
107
- services: null,
108
- warnings: [],
109
- errors: [backendResult.error]
110
- };
111
- }
112
- if (Object.keys(backendResult.services).length === 0) {
113
- return {
114
- services: null,
115
- warnings: [],
116
- errors: []
117
- };
118
- }
119
- Object.assign(services, backendResult.services);
120
- const mountWarnings = (0, import_utils.assignMountPaths)(services);
121
- return {
122
- services,
123
- warnings: mountWarnings,
124
- errors: []
125
- };
126
- }
127
- async function detectServicesFrontendSubdir(fs, frontendFramework, frontendLocation, detectEntrypoint) {
128
- const services = {};
129
- const serviceName = frontendLocation.split("/").pop() || "frontend";
130
- services[serviceName] = {
131
- framework: frontendFramework.slug ?? void 0,
132
- root: frontendLocation,
133
- mountPath: "/"
134
- };
135
- const backendResult = await detectBackendServices(fs, detectEntrypoint);
136
- if (backendResult.error) {
137
- return {
138
- services: null,
139
- warnings: [],
140
- errors: [backendResult.error]
141
- };
142
- }
143
- if (Object.keys(backendResult.services).length === 0) {
144
- return {
145
- services: null,
146
- warnings: [],
147
- errors: [
148
- {
149
- code: "NO_BACKEND_SERVICES",
150
- message: `Frontend detected in ${frontendLocation}/ but no backend services found. Add a backend/ or services/ directory with a supported framework.`
151
- }
152
- ]
153
- };
154
- }
155
- Object.assign(services, backendResult.services);
156
- const mountWarnings = (0, import_utils.assignMountPaths)(services);
157
- return {
158
- services,
159
- warnings: mountWarnings,
160
- errors: []
161
- };
162
- }
163
- async function detectBackendServices(fs, detectEntrypoint) {
164
- const services = {};
165
- const backendResult = await detectServiceInDir(
166
- fs,
167
- BACKEND_DIR,
168
- "backend",
169
- detectEntrypoint
170
- );
171
- if (backendResult.error) {
172
- return { services: {}, error: backendResult.error };
173
- }
174
- if (backendResult.service) {
175
- services.backend = backendResult.service;
176
- }
177
- const multiServicesResult = await detectServicesDirectory(
178
- fs,
179
- detectEntrypoint
180
- );
181
- if (multiServicesResult.error) {
182
- return { services: {}, error: multiServicesResult.error };
183
- }
184
- for (const serviceName of Object.keys(multiServicesResult.services)) {
185
- if (services[serviceName]) {
186
- return {
187
- services: {},
188
- error: {
189
- code: "SERVICE_NAME_CONFLICT",
190
- message: `Service name conflict: "${serviceName}" exists in both ${BACKEND_DIR}/ and ${SERVICES_DIR}/${serviceName}/. Rename one of the directories or use explicit services config.`,
191
- serviceName
192
- }
193
- };
194
- }
195
- }
196
- Object.assign(services, multiServicesResult.services);
197
- return { services };
198
- }
199
- async function detectServicesDirectory(fs, detectEntrypoint) {
200
- const services = {};
201
- const hasServicesDir = await fs.hasPath(SERVICES_DIR);
202
- if (!hasServicesDir) {
203
- return { services };
204
- }
205
- const servicesFs = fs.chdir(SERVICES_DIR);
206
- const entries = await servicesFs.readdir("/");
207
- for (const entry of entries) {
208
- if (entry.type !== "dir") {
209
- continue;
210
- }
211
- const serviceName = entry.name;
212
- const serviceDir = `${SERVICES_DIR}/${serviceName}`;
213
- const result = await detectServiceInDir(
214
- fs,
215
- serviceDir,
216
- serviceName,
217
- detectEntrypoint
218
- );
219
- if (result.error) {
220
- return { services: {}, error: result.error };
221
- }
222
- if (result.service) {
223
- services[serviceName] = result.service;
224
- }
225
- }
226
- return { services };
227
- }
228
- async function detectServiceInDir(fs, dirPath, serviceName, detectEntrypoint) {
229
- const hasDirPath = await fs.hasPath(dirPath);
230
- if (!hasDirPath) {
231
- return {};
232
- }
233
- const serviceFs = fs.chdir(dirPath);
234
- const frameworks = await (0, import_detect_framework.detectFrameworks)({
235
- fs: serviceFs,
236
- frameworkList: import_utils.DETECTION_FRAMEWORKS,
237
- useExperimentalFrameworks: true
238
- });
239
- if (frameworks.length > 1) {
240
- const frameworkNames = frameworks.map((f) => f.name).join(", ");
241
- return {
242
- error: {
243
- code: "MULTIPLE_FRAMEWORKS_SERVICE",
244
- message: `Multiple frameworks detected in ${dirPath}/: ${frameworkNames}. Use explicit services config.`,
245
- serviceName
246
- }
247
- };
248
- }
249
- if (frameworks.length !== 1) {
250
- return {};
251
- }
252
- const framework = frameworks[0];
253
- const slug = framework.slug ?? void 0;
254
- const mountPath = `/${serviceName}`;
255
- const detected = detectEntrypoint && !(0, import_utils.isFrontendFramework)(slug) ? await detectEntrypoint({ workPath: dirPath, framework: slug }) : null;
256
- return {
257
- service: {
258
- framework: slug,
259
- root: dirPath,
260
- ...detected ? { entrypoint: detected.entrypoint } : {},
261
- mountPath
262
- }
263
- };
264
- }
265
- // Annotate the CommonJS export names for ESM import in node:
266
- 0 && (module.exports = {
267
- autoDetectServices
268
- });
@@ -1,22 +0,0 @@
1
- import type { DetectorFilesystem } from '../detectors/filesystem';
2
- import type { InferredServicesConfig, ServiceDetectionError, ServiceDetectionWarning } from './types';
3
- export interface ProcfileDetectResult {
4
- services: InferredServicesConfig | null;
5
- errors: ServiceDetectionError[];
6
- warnings: ServiceDetectionWarning[];
7
- }
8
- /**
9
- * Detect service configurations from a Procfile.
10
- *
11
- * We infer runtime and entrypoint from the start command where possible,
12
- * then run framework detection from the project root to fill in the framework.
13
- *
14
- * Process type mapping:
15
- * - `web`: web service
16
- * - `release`: embeded into one of web service's buildCommand
17
- * - `worker`-like process name: try to infer entrypoint for support Python worker or produce a hint
18
- * - everything else is tried to be inferred as `web` or produces a hint
19
- */
20
- export declare function detectProcfileServices(options: {
21
- fs: DetectorFilesystem;
22
- }): Promise<ProcfileDetectResult>;