@vercel/fs-detectors 6.11.1 → 6.11.3

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.
@@ -30,7 +30,14 @@ var import_types = require("./types");
30
30
  var import_resolve = require("./resolve");
31
31
  var import_utils = require("./utils");
32
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])?$/;
33
+ const MAX_SERVICE_NAME_LENGTH = 64;
34
+ const SERVICE_NAME_REGEX = /^[a-z]([a-z_-]*[a-z])?$/;
35
+ function isValidServiceName(name) {
36
+ return name.length <= MAX_SERVICE_NAME_LENGTH && SERVICE_NAME_REGEX.test(name);
37
+ }
38
+ function getInvalidServiceNameMessage(name) {
39
+ return `Service name "${name}" is invalid. Names must be 1-${MAX_SERVICE_NAME_LENGTH} characters, start and end with a lowercase letter, and contain only lowercase letters, hyphens, and underscores.`;
40
+ }
34
41
  const CONTAINER_ENTRYPOINT_CANDIDATES = [
35
42
  "Dockerfile.vercel",
36
43
  "Containerfile.vercel",
@@ -122,10 +129,10 @@ async function resolveContainerServiceV2(name, config, normalizedRoot, serviceFs
122
129
  };
123
130
  }
124
131
  function validateServiceConfigV2(name, config) {
125
- if (!SERVICE_NAME_REGEX.test(name)) {
132
+ if (!isValidServiceName(name)) {
126
133
  return {
127
134
  code: "INVALID_SERVICE_NAME",
128
- 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.`,
135
+ message: getInvalidServiceNameMessage(name),
129
136
  serviceName: name
130
137
  };
131
138
  }
@@ -182,14 +189,6 @@ function validateServiceConfigV2(name, config) {
182
189
  };
183
190
  }
184
191
  }
185
- const isContainer = config.runtime === "container";
186
- if (!config.framework && !config.entrypoint && !isContainer) {
187
- return {
188
- code: "MISSING_SERVICE_CONFIG",
189
- message: `Service "${name}" must specify "framework" or "entrypoint".`,
190
- serviceName: name
191
- };
192
- }
193
192
  return null;
194
193
  }
195
194
  async function resolveConfiguredServiceV2(name, config, fs) {
@@ -221,14 +220,15 @@ async function resolveConfiguredServiceV2(name, config, fs) {
221
220
  entrypointIsDirectory = Boolean(resolved.entrypoint?.isDirectory);
222
221
  }
223
222
  const entrypointFile = entrypointIsDirectory || !normalizedEntrypoint ? void 0 : normalizedEntrypoint;
224
- const inferredRuntime = (0, import_utils.inferServiceRuntime)({
223
+ let inferredRuntime = (0, import_utils.inferServiceRuntime)({
225
224
  runtime: config.runtime,
226
225
  framework: config.framework,
227
226
  entrypoint: entrypointFile
228
227
  });
229
228
  let framework = config.framework;
230
- if (!framework && normalizedEntrypoint) {
231
- const workspace = entrypointIsDirectory ? normalizedEntrypoint : import_path.posix.dirname(normalizedEntrypoint) || ".";
229
+ let detectedFramework = false;
230
+ if (!framework) {
231
+ const workspace = normalizedEntrypoint ? entrypointIsDirectory ? normalizedEntrypoint : import_path.posix.dirname(normalizedEntrypoint) || "." : ".";
232
232
  const detection = await (0, import_resolve.detectFrameworkFromWorkspace)({
233
233
  fs: serviceFs,
234
234
  workspace,
@@ -239,6 +239,12 @@ async function resolveConfiguredServiceV2(name, config, fs) {
239
239
  return { error: detection.error };
240
240
  }
241
241
  framework = detection.framework;
242
+ detectedFramework = Boolean(framework);
243
+ inferredRuntime = (0, import_utils.inferServiceRuntime)({
244
+ runtime: config.runtime,
245
+ framework,
246
+ entrypoint: entrypointFile
247
+ });
242
248
  }
243
249
  if (entrypointIsDirectory && !framework) {
244
250
  return {
@@ -249,6 +255,16 @@ async function resolveConfiguredServiceV2(name, config, fs) {
249
255
  }
250
256
  };
251
257
  }
258
+ const frameworkRuntime = (0, import_utils.inferRuntimeFromFramework)(framework);
259
+ if (detectedFramework && frameworkRuntime && !entrypointFile) {
260
+ return {
261
+ error: {
262
+ code: "MISSING_SERVICE_CONFIG",
263
+ message: `Service "${name}" detected framework "${framework}" in "${normalizedRoot}" and must specify an "entrypoint" for runtime "${frameworkRuntime}".`,
264
+ serviceName: name
265
+ }
266
+ };
267
+ }
252
268
  const frameworkDefinition = framework ? frameworksBySlug.get(framework) : void 0;
253
269
  let builderUse;
254
270
  let builderSrc;
@@ -257,16 +273,26 @@ async function resolveConfiguredServiceV2(name, config, fs) {
257
273
  builderSrc = entrypointFile || frameworkDefinition?.useRuntime?.src || "package.json";
258
274
  } else {
259
275
  if (!inferredRuntime) {
260
- return {
261
- error: {
262
- code: "MISSING_SERVICE_CONFIG",
263
- message: `Service "${name}" must specify "framework" or a runtime-resolvable "entrypoint".`,
264
- serviceName: name
265
- }
266
- };
276
+ if (config.buildCommand) {
277
+ builderUse = "@vercel/static-build";
278
+ builderSrc = "package.json";
279
+ } else {
280
+ builderUse = "@vercel/static";
281
+ builderSrc = config.outputDirectory ? import_path.posix.join(config.outputDirectory, "**") : "**";
282
+ }
283
+ } else {
284
+ if (!entrypointFile) {
285
+ return {
286
+ error: {
287
+ code: "MISSING_SERVICE_CONFIG",
288
+ message: `Service "${name}" must specify an "entrypoint" for runtime "${inferredRuntime}".`,
289
+ serviceName: name
290
+ }
291
+ };
292
+ }
293
+ builderUse = inferredRuntime === "node" ? "@vercel/backends" : (0, import_utils.getBuilderForRuntime)(inferredRuntime);
294
+ builderSrc = entrypointFile;
267
295
  }
268
- builderUse = inferredRuntime === "node" ? "@vercel/backends" : (0, import_utils.getBuilderForRuntime)(inferredRuntime);
269
- builderSrc = entrypointFile;
270
296
  }
271
297
  const isRoot = normalizedRoot === ".";
272
298
  const projectRelativeSrc = isRoot ? builderSrc : import_path.posix.join(normalizedRoot, builderSrc);
@@ -277,6 +303,9 @@ async function resolveConfiguredServiceV2(name, config, fs) {
277
303
  if (framework) {
278
304
  builderConfig.framework = framework;
279
305
  }
306
+ if (config.outputDirectory) {
307
+ builderConfig.outputDirectory = config.outputDirectory;
308
+ }
280
309
  if (!isRoot) {
281
310
  builderConfig.workspace = normalizedRoot;
282
311
  }
@@ -339,6 +368,14 @@ async function resolveAllConfiguredServicesV2(services, fs) {
339
368
  const serviceNames = new Set(Object.keys(services));
340
369
  for (const service of resolved) {
341
370
  for (const binding of service.bindings ?? []) {
371
+ if (!isValidServiceName(binding.service)) {
372
+ errors.push({
373
+ code: "INVALID_SERVICE_BINDING_NAME",
374
+ message: `Service "${service.name}" declares an invalid binding service name "${binding.service}". ${getInvalidServiceNameMessage(binding.service)}`,
375
+ serviceName: service.name
376
+ });
377
+ continue;
378
+ }
342
379
  if (!serviceNames.has(binding.service)) {
343
380
  errors.push({
344
381
  code: "UNKNOWN_SERVICE_BINDING",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/fs-detectors",
3
- "version": "6.11.1",
3
+ "version": "6.11.3",
4
4
  "description": "Vercel filesystem detectors",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -20,9 +20,9 @@
20
20
  "minimatch": "3.1.2",
21
21
  "semver": "6.3.1",
22
22
  "smol-toml": "1.5.2",
23
- "@vercel/error-utils": "2.2.0",
24
23
  "@vercel/build-utils": "13.32.2",
25
- "@vercel/frameworks": "3.30.1",
24
+ "@vercel/error-utils": "2.2.0",
25
+ "@vercel/frameworks": "3.30.2",
26
26
  "@vercel/routing-utils": "6.4.0"
27
27
  },
28
28
  "devDependencies": {