@farm.js/cli 0.1.0-beta.16 → 0.1.0-beta.18
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/bin/farm.js +4 -2
- package/dist/index.js +111 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -60
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/bin/farm.js
CHANGED
|
@@ -468,8 +468,10 @@ program
|
|
|
468
468
|
const { deployFarm } = require("../dist/index.js");
|
|
469
469
|
await deployFarm(options);
|
|
470
470
|
} catch (error) {
|
|
471
|
-
|
|
472
|
-
|
|
471
|
+
const code = error?.name === "FarmDeployError" ? ` [${error.code}]` : "";
|
|
472
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
473
|
+
console.error(`Failed to deploy${code}: ${message}`);
|
|
474
|
+
process.exitCode = 1;
|
|
473
475
|
}
|
|
474
476
|
});
|
|
475
477
|
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,15 @@ let croner = require("croner");
|
|
|
19
19
|
let node_module = require("node:module");
|
|
20
20
|
let node_url = require("node:url");
|
|
21
21
|
//#region src/deploy.ts
|
|
22
|
+
var FarmDeployError = class extends Error {
|
|
23
|
+
constructor(code, platform, message, options) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "FarmDeployError";
|
|
26
|
+
this.code = code;
|
|
27
|
+
this.platform = platform;
|
|
28
|
+
this.cause = options?.cause;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
22
31
|
/**
|
|
23
32
|
* Deploy Farm.js application
|
|
24
33
|
*/
|
|
@@ -33,7 +42,7 @@ async function deployFarm(options = {}) {
|
|
|
33
42
|
root: plan.root,
|
|
34
43
|
preset: plan.preset
|
|
35
44
|
});
|
|
36
|
-
if (!(0, fs.existsSync)(plan.outputDir)) throw new
|
|
45
|
+
if (!(0, fs.existsSync)(plan.outputDir)) throw new FarmDeployError("INVALID_BUILD_OUTPUT", plan.target, `Build output not found at ${plan.outputDir}. Please run 'farm build' first.`);
|
|
37
46
|
await deployPlatform(plan.target, plan.root, plan.outputDir, deployConfig, options.prod);
|
|
38
47
|
return plan;
|
|
39
48
|
}
|
|
@@ -95,26 +104,64 @@ async function resolveFarmDeployContext(options) {
|
|
|
95
104
|
};
|
|
96
105
|
}
|
|
97
106
|
function createDeployCommand(platform, root, outputDir, deployConfig, prod, cloudflareAgent) {
|
|
98
|
-
if (platform === "vercel")
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
if (platform === "vercel") {
|
|
108
|
+
const args = [
|
|
109
|
+
"deploy",
|
|
110
|
+
"--prebuilt",
|
|
111
|
+
"--yes",
|
|
112
|
+
...prod ? ["--prod"] : []
|
|
113
|
+
];
|
|
114
|
+
return {
|
|
115
|
+
command: formatCommand$1("vercel", args),
|
|
116
|
+
cwd: path.default.resolve(root),
|
|
117
|
+
executable: "vercel",
|
|
118
|
+
args
|
|
119
|
+
};
|
|
120
|
+
}
|
|
102
121
|
if (platform === "netlify") {
|
|
103
|
-
const
|
|
122
|
+
const args = createNetlifyDeployArgs(deployConfig.netlify?.site);
|
|
104
123
|
return {
|
|
105
|
-
command:
|
|
106
|
-
cwd: outputDir
|
|
124
|
+
command: formatCommand$1("netlify", args),
|
|
125
|
+
cwd: outputDir,
|
|
126
|
+
executable: "netlify",
|
|
127
|
+
args
|
|
107
128
|
};
|
|
108
129
|
}
|
|
109
|
-
if (cloudflareAgent)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
130
|
+
if (cloudflareAgent) {
|
|
131
|
+
const args = [
|
|
132
|
+
"deploy",
|
|
133
|
+
"--config",
|
|
134
|
+
cloudflareAgent.configPath,
|
|
135
|
+
...cloudflareAgent.environment ? ["--env", cloudflareAgent.environment] : []
|
|
136
|
+
];
|
|
137
|
+
return {
|
|
138
|
+
command: formatCommand$1("wrangler", args),
|
|
139
|
+
cwd: path.default.resolve(root),
|
|
140
|
+
executable: "wrangler",
|
|
141
|
+
args
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const args = [
|
|
145
|
+
"pages",
|
|
146
|
+
"deploy",
|
|
147
|
+
".",
|
|
148
|
+
`--project-name=${deployConfig.cloudflare?.projectName || deployConfig.projectName || "farm-app"}`
|
|
149
|
+
];
|
|
113
150
|
return {
|
|
114
|
-
command:
|
|
115
|
-
cwd: outputDir
|
|
151
|
+
command: formatCommand$1("wrangler", args),
|
|
152
|
+
cwd: outputDir,
|
|
153
|
+
executable: "wrangler",
|
|
154
|
+
args
|
|
116
155
|
};
|
|
117
156
|
}
|
|
157
|
+
function createNetlifyDeployArgs(site) {
|
|
158
|
+
return [
|
|
159
|
+
"deploy",
|
|
160
|
+
"--prod",
|
|
161
|
+
"--dir=.",
|
|
162
|
+
...site ? [`--site=${site}`] : []
|
|
163
|
+
];
|
|
164
|
+
}
|
|
118
165
|
/**
|
|
119
166
|
* Deploy using platform's native CLI (user credentials)
|
|
120
167
|
*/
|
|
@@ -135,19 +182,20 @@ async function deployPlatform(platform, root, outputDir, deployConfig, prod) {
|
|
|
135
182
|
async function deployVercel(root, outputDir, prod) {
|
|
136
183
|
_farm_js_core.logger.info("🚀 Deploying to Vercel...");
|
|
137
184
|
try {
|
|
138
|
-
(0, child_process.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
185
|
+
(0, child_process.execFileSync)("vercel", ["--version"], {
|
|
186
|
+
stdio: "ignore",
|
|
187
|
+
cwd: root
|
|
188
|
+
});
|
|
189
|
+
} catch (error) {
|
|
190
|
+
throw new FarmDeployError("CLI_NOT_INSTALLED", "vercel", "Vercel CLI is not installed. Install it with: npm i -g vercel", { cause: error });
|
|
143
191
|
}
|
|
144
192
|
try {
|
|
145
|
-
(0, child_process.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
193
|
+
(0, child_process.execFileSync)("vercel", ["whoami"], {
|
|
194
|
+
stdio: "ignore",
|
|
195
|
+
cwd: root
|
|
196
|
+
});
|
|
197
|
+
} catch (error) {
|
|
198
|
+
throw new FarmDeployError("CLI_NOT_AUTHENTICATED", "vercel", "Vercel CLI is not authenticated. Run 'vercel login', then retry the deployment.", { cause: error });
|
|
151
199
|
}
|
|
152
200
|
try {
|
|
153
201
|
const { existsSync, statSync, readdirSync } = await import("fs");
|
|
@@ -156,14 +204,8 @@ async function deployVercel(root, outputDir, prod) {
|
|
|
156
204
|
const configFile = path.default.join(outputDir, "config.json");
|
|
157
205
|
const serverIndex = path.default.join(functionsDir, "index.mjs");
|
|
158
206
|
_farm_js_core.logger.info("🔍 Verifying deployment structure...");
|
|
159
|
-
if (!existsSync(functionsDir)) {
|
|
160
|
-
|
|
161
|
-
process.exit(1);
|
|
162
|
-
}
|
|
163
|
-
if (!existsSync(serverIndex)) {
|
|
164
|
-
_farm_js_core.logger.error(`❌ Server entry point not found at ${serverIndex}`);
|
|
165
|
-
process.exit(1);
|
|
166
|
-
}
|
|
207
|
+
if (!existsSync(functionsDir)) throw new FarmDeployError("INVALID_BUILD_OUTPUT", "vercel", `Functions directory not found at ${functionsDir}.`);
|
|
208
|
+
if (!existsSync(serverIndex)) throw new FarmDeployError("INVALID_BUILD_OUTPUT", "vercel", `Server entry point not found at ${serverIndex}.`);
|
|
167
209
|
_farm_js_core.logger.info(`✅ Functions directory: ${functionsDir}`);
|
|
168
210
|
if (!existsSync(staticDir)) _farm_js_core.logger.warn(`⚠️ Static directory not found at ${staticDir}`);
|
|
169
211
|
else {
|
|
@@ -244,14 +286,19 @@ async function deployVercel(root, outputDir, prod) {
|
|
|
244
286
|
_farm_js_core.logger.info(` Static: ${staticDir}`);
|
|
245
287
|
_farm_js_core.logger.info(` Config: ${configFile}`);
|
|
246
288
|
_farm_js_core.logger.info("📤 Uploading to Vercel...");
|
|
247
|
-
(0, child_process.
|
|
289
|
+
(0, child_process.execFileSync)("vercel", [
|
|
290
|
+
"deploy",
|
|
291
|
+
"--prebuilt",
|
|
292
|
+
"--yes",
|
|
293
|
+
...prod ? ["--prod"] : []
|
|
294
|
+
], {
|
|
248
295
|
stdio: "inherit",
|
|
249
296
|
cwd: root
|
|
250
297
|
});
|
|
251
298
|
_farm_js_core.logger.success("✅ Deployed to Vercel successfully!");
|
|
252
299
|
} catch (error) {
|
|
253
|
-
|
|
254
|
-
|
|
300
|
+
if (error instanceof FarmDeployError) throw error;
|
|
301
|
+
throw new FarmDeployError("DEPLOY_FAILED", "vercel", `Failed to deploy to Vercel: ${getErrorMessage(error)}`, { cause: error });
|
|
255
302
|
}
|
|
256
303
|
}
|
|
257
304
|
/** Deploy to a composed Worker or fall back to Cloudflare Pages. */
|
|
@@ -272,8 +319,7 @@ async function deployCloudflare(root, outputDir, projectName) {
|
|
|
272
319
|
});
|
|
273
320
|
_farm_js_core.logger.success("✅ Deployed Farm and Cloudflare Agents successfully!");
|
|
274
321
|
} catch (error) {
|
|
275
|
-
|
|
276
|
-
process.exit(1);
|
|
322
|
+
throw new FarmDeployError("DEPLOY_FAILED", "cloudflare", `Failed to deploy to Cloudflare: ${getErrorMessage(error)}`, { cause: error });
|
|
277
323
|
}
|
|
278
324
|
return;
|
|
279
325
|
}
|
|
@@ -291,8 +337,7 @@ async function deployCloudflare(root, outputDir, projectName) {
|
|
|
291
337
|
});
|
|
292
338
|
_farm_js_core.logger.success("✅ Deployed to Cloudflare Pages successfully!");
|
|
293
339
|
} catch (error) {
|
|
294
|
-
|
|
295
|
-
process.exit(1);
|
|
340
|
+
throw new FarmDeployError("DEPLOY_FAILED", "cloudflare", `Failed to deploy to Cloudflare: ${getErrorMessage(error)}`, { cause: error });
|
|
296
341
|
}
|
|
297
342
|
}
|
|
298
343
|
/** Read the trusted Workers deployment handoff emitted by @farm.js/cf-agent. */
|
|
@@ -344,10 +389,8 @@ function assertWranglerInstalled(root) {
|
|
|
344
389
|
stdio: "ignore",
|
|
345
390
|
cwd: root
|
|
346
391
|
});
|
|
347
|
-
} catch {
|
|
348
|
-
|
|
349
|
-
_farm_js_core.logger.info("💡 Install it in this project with: npm i -D wrangler");
|
|
350
|
-
process.exit(1);
|
|
392
|
+
} catch (error) {
|
|
393
|
+
throw new FarmDeployError("CLI_NOT_INSTALLED", "cloudflare", "Wrangler CLI is not installed. Install it in this project with: npm i -D wrangler", { cause: error });
|
|
351
394
|
}
|
|
352
395
|
}
|
|
353
396
|
function isRecord(value) {
|
|
@@ -359,22 +402,33 @@ function isRecord(value) {
|
|
|
359
402
|
async function deployNetlify(root, outputDir, site) {
|
|
360
403
|
_farm_js_core.logger.info("🚀 Deploying to Netlify...");
|
|
361
404
|
try {
|
|
362
|
-
(0, child_process.
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
405
|
+
(0, child_process.execFileSync)("netlify", ["--version"], {
|
|
406
|
+
stdio: "ignore",
|
|
407
|
+
cwd: root
|
|
408
|
+
});
|
|
409
|
+
} catch (error) {
|
|
410
|
+
throw new FarmDeployError("CLI_NOT_INSTALLED", "netlify", "Netlify CLI is not installed. Install it with: npm i -g netlify-cli", { cause: error });
|
|
367
411
|
}
|
|
368
412
|
try {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
413
|
+
(0, child_process.execFileSync)("netlify", createNetlifyDeployArgs(site), {
|
|
414
|
+
stdio: "inherit",
|
|
415
|
+
cwd: outputDir
|
|
416
|
+
});
|
|
372
417
|
_farm_js_core.logger.success("✅ Deployed to Netlify successfully!");
|
|
373
418
|
} catch (error) {
|
|
374
|
-
|
|
375
|
-
process.exit(1);
|
|
419
|
+
throw new FarmDeployError("DEPLOY_FAILED", "netlify", `Failed to deploy to Netlify: ${getErrorMessage(error)}`, { cause: error });
|
|
376
420
|
}
|
|
377
421
|
}
|
|
422
|
+
function formatCommand$1(executable, args) {
|
|
423
|
+
return [executable, ...args].map(formatCommandArgument).join(" ");
|
|
424
|
+
}
|
|
425
|
+
function formatCommandArgument(argument) {
|
|
426
|
+
if (/^[A-Za-z0-9_./:=@+-]+$/.test(argument)) return argument;
|
|
427
|
+
return `'${argument.replace(/'/g, `'"'"'`)}'`;
|
|
428
|
+
}
|
|
429
|
+
function getErrorMessage(error) {
|
|
430
|
+
return error instanceof Error ? error.message : String(error);
|
|
431
|
+
}
|
|
378
432
|
//#endregion
|
|
379
433
|
//#region src/preview-gateway.ts
|
|
380
434
|
const DEFAULT_GATEWAY_URL = "https://preview.farming-labs.dev";
|
|
@@ -2072,9 +2126,8 @@ function discoverMatchingPages(config, pathname) {
|
|
|
2072
2126
|
}
|
|
2073
2127
|
const sourceDirectory = node_path.default.join(source.root, source.srcDir);
|
|
2074
2128
|
if (!(0, node_fs.existsSync)(sourceDirectory)) continue;
|
|
2075
|
-
for (const
|
|
2076
|
-
if (
|
|
2077
|
-
const filePath = node_path.default.join(sourceDirectory, entry.name);
|
|
2129
|
+
for (const filePath of walkFiles(sourceDirectory)) {
|
|
2130
|
+
if (!/\.(?:tsx?|jsx?)$/.test(filePath) || filePath.endsWith(".d.ts")) continue;
|
|
2078
2131
|
const moduleSource = (0, node_fs.readFileSync)(filePath, "utf8");
|
|
2079
2132
|
for (const pattern of (0, _farm_js_core.scanProgrammaticPagePaths)(moduleSource)) {
|
|
2080
2133
|
const match = matchRoutePattern(pattern, pathname);
|
|
@@ -3153,6 +3206,7 @@ function formatError(error) {
|
|
|
3153
3206
|
return error instanceof Error ? error.message : String(error);
|
|
3154
3207
|
}
|
|
3155
3208
|
//#endregion
|
|
3209
|
+
exports.FarmDeployError = FarmDeployError;
|
|
3156
3210
|
exports.FarmGeneratedArtifactsStaleError = FarmGeneratedArtifactsStaleError;
|
|
3157
3211
|
exports.addFarmIntegration = require_add_integration.addFarmIntegration;
|
|
3158
3212
|
exports.buildFarm = require_build.buildFarm;
|