@vercel/fs-detectors 5.18.0 → 5.18.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.
|
@@ -80,7 +80,8 @@ async function detectRailwayServices(options) {
|
|
|
80
80
|
const schedule = cf.config.deploy.cronSchedule;
|
|
81
81
|
const runtime = frameworks.length === 1 ? (0, import_utils.inferRuntimeFromFramework)(frameworks[0].slug) : void 0;
|
|
82
82
|
const hint = {
|
|
83
|
-
type: "
|
|
83
|
+
type: "job",
|
|
84
|
+
trigger: "schedule",
|
|
84
85
|
schedule,
|
|
85
86
|
entrypoint: "<path-to-handler>"
|
|
86
87
|
};
|
|
@@ -89,7 +90,7 @@ async function detectRailwayServices(options) {
|
|
|
89
90
|
}
|
|
90
91
|
warnings.push({
|
|
91
92
|
code: "RAILWAY_CRON_HINT",
|
|
92
|
-
message: `Found Railway cron in ${dirLabel}/ (schedule: "${schedule}"). Vercel crons work with a file entrypoint. You can add the following to define this
|
|
93
|
+
message: `Found Railway cron in ${dirLabel}/ (schedule: "${schedule}"). Vercel crons work with a file entrypoint. You can add the following to define this scheduled job service:
|
|
93
94
|
"${deriveServiceName(cf.dirPath)}": ${JSON.stringify(hint, null, 2)}`
|
|
94
95
|
});
|
|
95
96
|
continue;
|
|
@@ -26,11 +26,11 @@ export declare function detectServices(options: DetectServicesOptions): Promise<
|
|
|
26
26
|
* Builders that provide their own routing (`@vercel/next`, `@vercel/backends`,
|
|
27
27
|
* Build Output API builders, etc.) are not given synthetic routes here.
|
|
28
28
|
*
|
|
29
|
-
* - Worker services:
|
|
29
|
+
* - Worker and queue-triggered job services:
|
|
30
30
|
* Internal queue callback routes under `/_svc/{serviceName}/workers/{entry}/{handler}`
|
|
31
31
|
* that rewrite to `/_svc/{serviceName}/index`.
|
|
32
32
|
*
|
|
33
|
-
* -
|
|
33
|
+
* - Schedule-triggered job services:
|
|
34
34
|
* Internal cron callback routes under `/_svc/{serviceName}/crons/{entry}/{handler}`
|
|
35
35
|
* that rewrite to `/_svc/{serviceName}/index`.
|
|
36
36
|
*/
|
|
@@ -22,6 +22,7 @@ __export(detect_services_exports, {
|
|
|
22
22
|
generateServicesRoutes: () => generateServicesRoutes
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(detect_services_exports);
|
|
25
|
+
var import_build_utils = require("@vercel/build-utils");
|
|
25
26
|
var import_routing_utils = require("@vercel/routing-utils");
|
|
26
27
|
var import_utils = require("./utils");
|
|
27
28
|
var import_resolve = require("./resolve");
|
|
@@ -255,7 +256,7 @@ function generateServicesRoutes(services) {
|
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
|
-
const workerServices = services.filter(
|
|
259
|
+
const workerServices = services.filter(import_build_utils.isQueueTriggeredService);
|
|
259
260
|
for (const service of workerServices) {
|
|
260
261
|
const workerEntrypoint = service.entrypoint || service.builder.src || "index";
|
|
261
262
|
const workerPath = (0, import_utils.getInternalServiceWorkerPath)(
|
|
@@ -269,7 +270,7 @@ function generateServicesRoutes(services) {
|
|
|
269
270
|
check: true
|
|
270
271
|
});
|
|
271
272
|
}
|
|
272
|
-
const cronServices = services.filter(
|
|
273
|
+
const cronServices = services.filter(import_build_utils.isScheduleTriggeredService);
|
|
273
274
|
for (const service of cronServices) {
|
|
274
275
|
const cronPrefix = (0, import_utils.getInternalServiceCronPathPrefix)(service.name);
|
|
275
276
|
const functionPath = (0, import_utils.getInternalServiceFunctionPath)(service.name);
|
package/dist/services/resolve.js
CHANGED
|
@@ -281,6 +281,12 @@ function validateServiceConfig(name, config) {
|
|
|
281
281
|
};
|
|
282
282
|
}
|
|
283
283
|
const serviceType = config.type || "web";
|
|
284
|
+
const isJobService = serviceType === "job" || serviceType === "cron";
|
|
285
|
+
const isScheduleJobService = serviceType === "cron" || serviceType === "job" && config.trigger === "schedule";
|
|
286
|
+
const isQueueJobService = serviceType === "job" && config.trigger === "queue";
|
|
287
|
+
const isWorkflowService = serviceType === "job" && config.trigger === "workflow";
|
|
288
|
+
const isNonWebService = serviceType === "worker" || isJobService;
|
|
289
|
+
const serviceTypeLabel = isJobService ? "Job" : serviceType === "worker" ? "Worker" : "Web";
|
|
284
290
|
const routingResult = resolveServiceRoutingConfig(name, config);
|
|
285
291
|
if (routingResult.error) {
|
|
286
292
|
return routingResult.error;
|
|
@@ -310,24 +316,52 @@ function validateServiceConfig(name, config) {
|
|
|
310
316
|
serviceName: name
|
|
311
317
|
};
|
|
312
318
|
}
|
|
313
|
-
if (
|
|
319
|
+
if (isNonWebService && configuredRoutePrefix) {
|
|
314
320
|
return {
|
|
315
321
|
code: "INVALID_ROUTE_PREFIX",
|
|
316
|
-
message: `${
|
|
322
|
+
message: `${serviceTypeLabel} service "${name}" cannot have "routePrefix" or "mount". Only web services should specify path-based routing.`,
|
|
317
323
|
serviceName: name
|
|
318
324
|
};
|
|
319
325
|
}
|
|
320
|
-
if (
|
|
326
|
+
if (isNonWebService && hasSubdomain) {
|
|
321
327
|
return {
|
|
322
328
|
code: "INVALID_HOST_ROUTING_CONFIG",
|
|
323
|
-
message: `${
|
|
329
|
+
message: `${serviceTypeLabel} service "${name}" cannot have "subdomain" or "mount.subdomain". Only web services should specify subdomain routing.`,
|
|
324
330
|
serviceName: name
|
|
325
331
|
};
|
|
326
332
|
}
|
|
327
|
-
if (serviceType === "
|
|
333
|
+
if (serviceType === "job" && config.trigger === void 0) {
|
|
328
334
|
return {
|
|
329
|
-
code: "
|
|
330
|
-
message: `
|
|
335
|
+
code: "MISSING_JOB_TRIGGER",
|
|
336
|
+
message: `Job service "${name}" is missing required "trigger" field.`,
|
|
337
|
+
serviceName: name
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
if (serviceType === "job" && config.trigger && !import_build_utils.JOB_TRIGGERS.includes(config.trigger)) {
|
|
341
|
+
return {
|
|
342
|
+
code: "INVALID_JOB_TRIGGER",
|
|
343
|
+
message: `Job service "${name}" has invalid trigger "${config.trigger}". Expected ${import_build_utils.JOB_TRIGGERS.map((t) => `"${t}"`).join(", ")}.`,
|
|
344
|
+
serviceName: name
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
if (isScheduleJobService && !config.schedule) {
|
|
348
|
+
return {
|
|
349
|
+
code: serviceType === "cron" ? "MISSING_CRON_SCHEDULE" : "MISSING_JOB_SCHEDULE",
|
|
350
|
+
message: `${serviceTypeLabel} service "${name}" is missing required "schedule" field.`,
|
|
351
|
+
serviceName: name
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
if (isQueueJobService && (!Array.isArray(config.topics) || config.topics.length === 0)) {
|
|
355
|
+
return {
|
|
356
|
+
code: "MISSING_QUEUE_TOPICS",
|
|
357
|
+
message: `${serviceTypeLabel} service "${name}" is missing required "topics" field.`,
|
|
358
|
+
serviceName: name
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
if (isWorkflowService && typeof config.entrypoint !== "string") {
|
|
362
|
+
return {
|
|
363
|
+
code: "MISSING_ENTRYPOINT",
|
|
364
|
+
message: `Job service "${name}" with "workflow" trigger must specify "entrypoint".`,
|
|
331
365
|
serviceName: name
|
|
332
366
|
};
|
|
333
367
|
}
|
|
@@ -428,6 +462,7 @@ async function resolveConfiguredService(options) {
|
|
|
428
462
|
routePrefixSource = "configured"
|
|
429
463
|
} = options;
|
|
430
464
|
const type = config.type || "web";
|
|
465
|
+
const trigger = type === "cron" ? "schedule" : type === "job" ? config.trigger : void 0;
|
|
431
466
|
const rawEntrypoint = config.entrypoint;
|
|
432
467
|
const moduleAttrParsed = typeof rawEntrypoint === "string" ? parsePyModuleAttrEntrypoint(rawEntrypoint) : null;
|
|
433
468
|
const routingResult = resolveServiceRoutingConfig(name, config);
|
|
@@ -484,7 +519,7 @@ async function resolveConfiguredService(options) {
|
|
|
484
519
|
workspace = workspace === "." ? normalizedRoot : import_path.posix.join(normalizedRoot, workspace);
|
|
485
520
|
}
|
|
486
521
|
}
|
|
487
|
-
const topics = type === "worker" ? (0, import_build_utils.
|
|
522
|
+
const topics = type === "worker" ? (0, import_build_utils.getServiceQueueTopics)({ type, topics: config.topics }) : trigger === "queue" ? config.topics : void 0;
|
|
488
523
|
const consumer = type === "worker" ? config.consumer || "default" : config.consumer;
|
|
489
524
|
let builderUse;
|
|
490
525
|
let builderSrc;
|
|
@@ -550,6 +585,7 @@ async function resolveConfiguredService(options) {
|
|
|
550
585
|
return {
|
|
551
586
|
name,
|
|
552
587
|
type,
|
|
588
|
+
trigger,
|
|
553
589
|
group,
|
|
554
590
|
workspace,
|
|
555
591
|
entrypoint: resolvedEntrypointFile,
|
package/dist/services/types.d.ts
CHANGED
|
@@ -22,8 +22,8 @@ export interface ServicesRoutes {
|
|
|
22
22
|
/** Default routes (catch-all for root web service) */
|
|
23
23
|
defaults: Route[];
|
|
24
24
|
/**
|
|
25
|
-
* Internal routes for
|
|
26
|
-
* These route `/_svc/{serviceName}/crons/{entry}/{handler}` to the
|
|
25
|
+
* Internal routes for schedule-triggered job services.
|
|
26
|
+
* These route `/_svc/{serviceName}/crons/{entry}/{handler}` to the scheduled job function.
|
|
27
27
|
*/
|
|
28
28
|
crons: Route[];
|
|
29
29
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/fs-detectors",
|
|
3
|
-
"version": "5.18.
|
|
3
|
+
"version": "5.18.3",
|
|
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/error-utils": "2.0.3",
|
|
24
23
|
"@vercel/frameworks": "3.24.1",
|
|
25
|
-
"@vercel/
|
|
26
|
-
"@vercel/
|
|
24
|
+
"@vercel/routing-utils": "6.1.1",
|
|
25
|
+
"@vercel/build-utils": "13.18.0",
|
|
26
|
+
"@vercel/error-utils": "2.0.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/glob": "7.2.0",
|