@vercel/queue 0.0.0-alpha.2 → 0.0.0-alpha.22

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.
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Standalone CLI script to discover queue handlers in development mode
5
+ * This script is self-contained and doesn't import from the main package
6
+ */
7
+
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+
11
+ function showHelp() {
12
+ console.log(`
13
+ @vercel/queue local-init - Initialize queue handlers in local development
14
+
15
+ USAGE:
16
+ npx vercel-queue-local-init [options]
17
+
18
+ OPTIONS:
19
+ --port <number> Port number for Next.js dev server (default: 3000)
20
+ --config <path> Path to vercel.json file (default: ./vercel.json)
21
+ --help, -h Show this help message
22
+
23
+ EXAMPLES:
24
+ npx vercel-queue-local-init
25
+ npx vercel-queue-local-init --port 3001
26
+ npx vercel-queue-local-init --config ./my-vercel.json
27
+ `);
28
+ }
29
+
30
+ /**
31
+ * Read vercel.json and extract function endpoints with queue triggers
32
+ */
33
+ function readVercelConfig(configPath = "./vercel.json") {
34
+ try {
35
+ const fullPath = path.resolve(configPath);
36
+ const configContent = fs.readFileSync(fullPath, "utf-8");
37
+ const config = JSON.parse(configContent);
38
+
39
+ const routes = [];
40
+
41
+ // Extract routes from functions with queue triggers
42
+ if (config.functions) {
43
+ for (const [functionPath, functionConfig] of Object.entries(
44
+ config.functions,
45
+ )) {
46
+ if (
47
+ functionConfig &&
48
+ typeof functionConfig === "object" &&
49
+ "experimentalTriggers" in functionConfig
50
+ ) {
51
+ const triggers = functionConfig.experimentalTriggers;
52
+ if (Array.isArray(triggers)) {
53
+ // Check if any trigger is a queue trigger
54
+ const hasQueueTrigger = triggers.some(
55
+ (trigger) =>
56
+ trigger &&
57
+ typeof trigger === "object" &&
58
+ trigger.type === "queue/v1beta",
59
+ );
60
+
61
+ if (hasQueueTrigger) {
62
+ // Convert file path to API route
63
+ // Examples:
64
+ // app/api/vm/queue/route.ts -> /api/vm/queue
65
+ // src/app/api/queue/route.ts -> /api/queue
66
+ // pages/api/queue.ts -> /api/queue
67
+ // src/pages/api/queue.ts -> /api/queue
68
+ // app/queue/route.ts -> /queue
69
+ // src/app/webhooks/route.ts -> /webhooks
70
+ let apiPath = functionPath;
71
+
72
+ // Handle src/ prefix
73
+ if (apiPath.startsWith("src/")) {
74
+ apiPath = apiPath.replace("src/", "");
75
+ }
76
+
77
+ // Convert Next.js file paths to HTTP routes
78
+ if (apiPath.startsWith("app/")) {
79
+ // App Router: app/api/queue/route.ts -> /api/queue
80
+ // App Router: app/queue/route.ts -> /queue
81
+ apiPath = apiPath.replace("app/", "/");
82
+ } else if (apiPath.startsWith("pages/api/")) {
83
+ // Pages Router: pages/api/queue.ts -> /api/queue
84
+ apiPath = apiPath.replace("pages/api/", "/api/");
85
+ } else if (apiPath.startsWith("pages/")) {
86
+ // Pages Router: pages/queue.ts -> /queue
87
+ apiPath = apiPath.replace("pages/", "/");
88
+ } else {
89
+ // Fallback: assume it's a root-level route
90
+ apiPath = "/" + apiPath;
91
+ }
92
+
93
+ // Remove file extensions and Next.js-specific suffixes
94
+ apiPath = apiPath.replace(
95
+ /\/(route|index)\.(ts|js|tsx|jsx)$/,
96
+ "",
97
+ );
98
+ apiPath = apiPath.replace(/\.(ts|js|tsx|jsx)$/, "");
99
+
100
+ routes.push(apiPath);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ return routes;
108
+ } catch (error) {
109
+ // vercel.json might not exist or be malformed
110
+ return [];
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Make OPTIONS requests to trigger Next.js lazy loading
116
+ */
117
+ async function discoverQueueHandlers(options = {}) {
118
+ const baseUrl = options.baseUrl || "http://localhost:3000";
119
+ const configPath = options.configPath || "./vercel.json";
120
+
121
+ let routes = options.routes || [];
122
+
123
+ // Auto-discover from vercel.json
124
+ if (routes.length === 0) {
125
+ const configRoutes = readVercelConfig(configPath);
126
+ if (configRoutes.length > 0) {
127
+ routes = configRoutes;
128
+ console.log(
129
+ `[Dev Mode] Found ${configRoutes.length} queue endpoints in vercel.json`,
130
+ );
131
+ } else {
132
+ console.error("[Dev Mode] No queue endpoints found in vercel.json");
133
+ process.exit(1);
134
+ }
135
+ }
136
+
137
+ console.log(
138
+ "[Dev Mode] Making OPTIONS requests to trigger module loading...",
139
+ );
140
+
141
+ for (const route of routes) {
142
+ try {
143
+ // Make an OPTIONS request to trigger module loading without processing
144
+ const response = await fetch(`${baseUrl}${route}`, {
145
+ method: "OPTIONS",
146
+ // Add a header to identify this as a discovery request
147
+ headers: { "x-queue-discovery": "true" },
148
+ });
149
+
150
+ // Any response means the route exists and module was loaded
151
+ console.log(`[Dev Mode] ✓ ${route} (${response.status})`);
152
+ } catch (error) {
153
+ // Ignore errors - route might not exist or server not running
154
+ console.log(`[Dev Mode] ✗ ${route} (server may not be running)`);
155
+ }
156
+ }
157
+
158
+ console.log("[Dev Mode] Module loading complete.");
159
+ }
160
+
161
+ async function main() {
162
+ const args = process.argv.slice(2);
163
+ const options = {};
164
+
165
+ // Parse simple command line arguments
166
+ for (let i = 0; i < args.length; i++) {
167
+ const arg = args[i];
168
+ if (arg === "--help" || arg === "-h") {
169
+ showHelp();
170
+ return;
171
+ } else if (arg === "--port" && args[i + 1]) {
172
+ options.baseUrl = `http://localhost:${args[i + 1]}`;
173
+ i++;
174
+ } else if (arg === "--config" && args[i + 1]) {
175
+ options.configPath = args[i + 1];
176
+ i++;
177
+ }
178
+ }
179
+
180
+ try {
181
+ await discoverQueueHandlers(options);
182
+ } catch (error) {
183
+ console.error("Failed to discover queue handlers:", error.message);
184
+ process.exit(1);
185
+ }
186
+ }
187
+
188
+ main();