@farm.js/cli 0.1.0-beta.3 → 0.1.0-beta.31

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/README.md CHANGED
@@ -8,4 +8,16 @@ Farm.js is currently in beta.
8
8
  npm install @farm.js/cli@beta
9
9
  ```
10
10
 
11
+ Upgrade every published `@farm.js/*` dependency in an app to one release channel:
12
+
13
+ ```bash
14
+ farm upgrade --latest
15
+ farm upgrade --beta
16
+ farm upgrade --latest --dry-run
17
+ ```
18
+
19
+ `--latest` selects the newest stable release. `--beta` selects the newest beta release. The CLI
20
+ detects npm, pnpm, Yarn, or Bun from the project and leaves `workspace:`, `file:`, and other local
21
+ package references unchanged.
22
+
11
23
  See the [Farm.js repository](https://github.com/farming-labs/farm.js) for documentation, examples, and support.
package/bin/farm.js CHANGED
@@ -16,14 +16,19 @@ const { program } = require("commander");
16
16
  const { version } = require("../package.json");
17
17
 
18
18
  const banner = `
19
- _______
20
- | ___ |__ _ _ __ _ __ ___
21
- | |_ /| / _\` | '__| '_ \` _ \\
22
- | _ \\| | (_| | | | | | | | |
23
- |_| \\_\\_|\\__,_|_| |_| |_| |_|
19
+ ░██████████ ░███ ░█████████ ░███ ░███ ░█████ ░██████
20
+ ░██ ░██░██ ░██ ░██ ░████ ░████ ░██ ░██ ░██
21
+ ░██ ░██ ░██ ░██ ░██ ░██░██ ░██░██ ░██ ░██
22
+ ░█████████ ░█████████ ░█████████ ░██ ░████ ░██ ░██ ░████████
23
+ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██
24
+ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██
25
+ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██████ ░██████
24
26
  `;
25
27
 
26
- program.name("farm").description("Farm.js CLI - A modern React meta-framework").version(version);
28
+ program
29
+ .name("farm")
30
+ .description("Farm.js CLI - A framework for product-integrated apps")
31
+ .version(version);
27
32
  program.addHelpText("beforeAll", `${banner}\n`);
28
33
 
29
34
  function collectOption(value, previous) {
@@ -33,7 +38,7 @@ function collectOption(value, previous) {
33
38
  program
34
39
  .command("dev")
35
40
  .description("Start development server")
36
- .option("-p, --port <port>", "Port to run the server on", "3000")
41
+ .option("-p, --port <port>", "Override the port to run the server on")
37
42
  .option("-r, --root <root>", "Root directory", process.cwd())
38
43
  .option("--cron", "Run configured cron routes in-process during development")
39
44
  .action(async (options) => {
@@ -43,12 +48,12 @@ program
43
48
  {
44
49
  root: options.root,
45
50
  },
46
- parseInt(options.port),
51
+ options.port === undefined ? undefined : parseInt(options.port, 10),
47
52
  );
48
53
  if (options.cron) {
49
54
  const { startFarmCronScheduler } = require("../dist/index.js");
50
55
  const address = server.httpServer?.address();
51
- const port = typeof address === "object" && address ? address.port : parseInt(options.port);
56
+ const port = typeof address === "object" && address ? address.port : 3000;
52
57
  const scheduler = await startFarmCronScheduler({
53
58
  root: options.root,
54
59
  url: `http://localhost:${port}`,
@@ -80,6 +85,59 @@ program
80
85
  }
81
86
  });
82
87
 
88
+ const authCommand = program.command("auth").description("Manage Farm-native authentication");
89
+
90
+ authCommand
91
+ .command("migrate")
92
+ .description("Create or update the Farm Auth database schema")
93
+ .option("-r, --root <root>", "Root directory", process.cwd())
94
+ .option("-c, --config <config>", "Path to farm config file")
95
+ .action(async (options) => {
96
+ try {
97
+ const { migrateFarmAuth } = require("../dist/index.js");
98
+ await migrateFarmAuth({
99
+ root: options.root,
100
+ configPath: options.config,
101
+ });
102
+ } catch (error) {
103
+ console.error("Failed to migrate Farm Auth:", error);
104
+ process.exit(1);
105
+ }
106
+ });
107
+
108
+ program
109
+ .command("upgrade")
110
+ .description("Upgrade installed Farm.js packages to a stable or beta release")
111
+ .option("-r, --root <root>", "Project root", process.cwd())
112
+ .option("--latest", "Upgrade to the latest stable release")
113
+ .option("--beta", "Upgrade to the latest beta release")
114
+ .option("--dry-run", "Print the package-manager commands without installing")
115
+ .action(async (options) => {
116
+ try {
117
+ if (options.latest === options.beta) {
118
+ throw new Error("Choose exactly one release channel: --latest (stable) or --beta.");
119
+ }
120
+
121
+ const { formatFarmUpgradePlan, upgradeFarm } = require("../dist/index.js");
122
+ const result = await upgradeFarm({
123
+ root: options.root,
124
+ channel: options.beta ? "beta" : "latest",
125
+ dryRun: options.dryRun,
126
+ });
127
+ console.log(formatFarmUpgradePlan(result.plan));
128
+ console.log(
129
+ result.executed
130
+ ? `Upgraded ${result.plan.packages.length} Farm package${
131
+ result.plan.packages.length === 1 ? "" : "s"
132
+ } to ${result.plan.channel}.`
133
+ : "Dry run only. No packages were changed.",
134
+ );
135
+ } catch (error) {
136
+ console.error("Failed to upgrade Farm packages:", error);
137
+ process.exit(1);
138
+ }
139
+ });
140
+
83
141
  program
84
142
  .command("generate")
85
143
  .description("Generate route/API types and integration schema artifacts")
@@ -91,6 +149,7 @@ program
91
149
  )
92
150
  .option("--dialect <dialect>", "SQL dialect for Drizzle generation (postgres, mysql, sqlite)")
93
151
  .option("-o, --output <output>", "Custom output path")
152
+ .option("--check", "Fail when committed generated framework types are stale")
94
153
  .action(async (options) => {
95
154
  try {
96
155
  const { generateFarmArtifacts } = require("../dist/index.js");
@@ -100,6 +159,7 @@ program
100
159
  orm: options.orm,
101
160
  dialect: options.dialect,
102
161
  output: options.output,
162
+ check: options.check,
103
163
  });
104
164
  } catch (error) {
105
165
  console.error("Failed to generate Farm artifacts:", error);
@@ -116,6 +176,7 @@ program
116
176
  .option("--host <host>", "Host of a running local app")
117
177
  .option("--url <url>", "Base URL of a running Farm app")
118
178
  .option("--offline", "Inspect project files without probing a running app")
179
+ .option("--fix", "Apply safe additive corrections without overwriting application files")
119
180
  .option("--timeout <ms>", "Live runtime probe timeout in milliseconds", "1200")
120
181
  .option("--json", "Print machine-readable JSON")
121
182
  .action(async (options) => {
@@ -132,6 +193,7 @@ program
132
193
  host: options.host,
133
194
  url: options.url,
134
195
  offline: options.offline,
196
+ fix: options.fix,
135
197
  timeoutMs,
136
198
  });
137
199
  console.log(options.json ? JSON.stringify(report, null, 2) : formatFarmDoctorReport(report));
@@ -142,6 +204,30 @@ program
142
204
  }
143
205
  });
144
206
 
207
+ program
208
+ .command("explain <path>")
209
+ .description("Explain how a URL maps to a Farm route and deployment runtime")
210
+ .option("-r, --root <root>", "Root directory", process.cwd())
211
+ .option("-c, --config <config>", "Path to farm config file")
212
+ .option("--json", "Print machine-readable JSON")
213
+ .action(async (pathname, options) => {
214
+ try {
215
+ const { explainFarmRoute, formatFarmRouteExplanation } = require("../dist/index.js");
216
+ const explanation = await explainFarmRoute(pathname, {
217
+ root: options.root,
218
+ configPath: options.config,
219
+ });
220
+ console.log(
221
+ options.json
222
+ ? JSON.stringify(explanation, null, 2)
223
+ : formatFarmRouteExplanation(explanation),
224
+ );
225
+ } catch (error) {
226
+ console.error("Failed to explain Farm route:", error);
227
+ process.exit(1);
228
+ }
229
+ });
230
+
145
231
  program
146
232
  .command("preview")
147
233
  .description("Create a public URL for a running local Farm app")
@@ -380,14 +466,17 @@ program
380
466
  .option("--cloudflare", "Deploy to Cloudflare")
381
467
  .option("--netlify", "Deploy to Netlify")
382
468
  .option("--prod", "Deploy to production (Vercel: uses prebuilt output)")
469
+ .option("--plan", "Print the resolved deployment plan without building or deploying")
383
470
  .option("--custom", "Use your own credentials (not Farm.js managed)")
384
471
  .action(async (options) => {
385
472
  try {
386
473
  const { deployFarm } = require("../dist/index.js");
387
474
  await deployFarm(options);
388
475
  } catch (error) {
389
- console.error("Failed to deploy:", error);
390
- process.exit(1);
476
+ const code = error?.name === "FarmDeployError" ? ` [${error.code}]` : "";
477
+ const message = error instanceof Error ? error.message : String(error);
478
+ console.error(`Failed to deploy${code}: ${message}`);
479
+ process.exitCode = 1;
391
480
  }
392
481
  });
393
482